欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android?Service完整實(shí)現(xiàn)流程分析

 更新時(shí)間:2023年01月02日 11:12:53   作者:失落夏天  
Android的服務(wù)是開發(fā)Android應(yīng)用程序的重要組成部分。不同于活動(dòng)Activity,服務(wù)是在后臺(tái)運(yùn)行,服務(wù)沒有接口,生命周期也與活動(dòng)Activity非常不同。通過使用服務(wù)我們可以實(shí)現(xiàn)一些后臺(tái)操作,比如想從遠(yuǎn)程服務(wù)器加載一個(gè)網(wǎng)頁等,下面來看看詳細(xì)內(nèi)容,需要的朋友可以參考下

前言

一開始的目標(biāo)是解決各種各樣的ANR問題的,我們知道,ANR總體上分有四種類型,這四種類型有三種是和四大組件相對(duì)應(yīng)的,所以,如果想了解ANR發(fā)生的根因,對(duì)安卓四大組件的實(shí)現(xiàn)流程是必須要了解的,都不明白ANR如何觸發(fā)的,怎么能完美的解決ANR的問題呢?

所以會(huì)寫一系列的文章,來分析四大組建的實(shí)現(xiàn)原理,同時(shí)也順帶講解四種類型的ANR是如何發(fā)生的。

本篇主要介紹service的完整實(shí)現(xiàn)流程,下一篇文章介紹Service中的ANR是如何產(chǎn)生的。

一.APP側(cè)啟動(dòng)Service

其實(shí)啟動(dòng)service和啟動(dòng)Activity是很相似的,都是APP通知系統(tǒng)側(cè),由系統(tǒng)側(cè)完成的整個(gè)流程。

1.1前臺(tái)和后臺(tái)啟動(dòng)

無論是Activity,還是service,還是Application,都繼承自Context的抽象類,所以可以使用Context的各種功能,就比如這了要介紹的啟動(dòng)前臺(tái)/后臺(tái)service。

Context在安卓中,使用了一種典型的代理模式,我們調(diào)用的startService或者startForegroundService方法,最終都會(huì)委托給ContextImpl中的startService和startForegroundService來處理的。我們就來看下ContextImpl中的這兩個(gè)方法:

@Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }
    @Override
    public ComponentName startForegroundService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, true, mUser);
    }

果然和我猜測的差不多,無論前臺(tái)還是后臺(tái)啟動(dòng),其實(shí)最終都會(huì)走到一個(gè)方法中,只是配置參數(shù)的區(qū)別而已。最終都會(huì)走執(zhí)行startServiceCommon方法。

1.2startServiceCommon

該方法中,通過binder通知系統(tǒng)的AMS完成對(duì)應(yīng)的service的啟動(dòng)操作:

 ComponentName cn = ActivityManager.getService().startService(
                    mMainThread.getApplicationThread(), service,
                    service.resolveTypeIfNeeded(getContentResolver()), requireForeground,
                    getOpPackageName(), getAttributionTag(), user.getIdentifier());

接下來,我們就看下系統(tǒng)側(cè)是如何處理Service啟動(dòng)流程的。

二.系統(tǒng)側(cè)分發(fā)處理Service的啟動(dòng)邏輯

系統(tǒng)側(cè)的處理我主要分為3塊來講:

1.系統(tǒng)接受APP側(cè)的通知并轉(zhuǎn)發(fā)

2.系統(tǒng)側(cè)委托ActiveServices負(fù)責(zé)完成的處理流程

3.收到APP側(cè)執(zhí)行完成的回調(diào),進(jìn)行收尾操作

2.1AMS接受啟動(dòng)service的通知

APP側(cè)持有system_server進(jìn)程的binder,上面講到,它會(huì)通過binder方法startService完成對(duì)系統(tǒng)側(cè)的通知。所以AMS的startService會(huì)收到這個(gè)通知。

我們看下代碼,發(fā)現(xiàn)AMS會(huì)把整個(gè)service的邏輯全部交由ActiveServices來處理,代碼如下:

 try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, callingFeatureId, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }

系統(tǒng)代碼startServiceLocked方法中,代碼雖然很長,但是卻遵循著一個(gè)不變的宗旨:位語句,即前面處理各種異常的分支邏輯,把核心流程留到方法的最終來處理。

所以我們直接看startServiceLocked方法的最后一部分即可:

final ComponentName realResult =
                startServiceInnerLocked(r, service, callingUid, callingPid, fgRequired, callerFg,
                allowBackgroundActivityStarts, backgroundActivityStartsToken);

startServiceInnerLocked方法中,處理邏輯也是比較簡單的,最終會(huì)交給bringUpServiceLocked方法來進(jìn)行處理。而bringUpServiceLocked方法中則最終會(huì)交給realStartServiceLocked完成整個(gè)流程。好像系統(tǒng)代碼都喜喜歡用realStart,Activity啟動(dòng)的流程中也有一個(gè)方法叫realStartActivity。

2.2realStartServiceLocked流程

realStartServiceLocked方法中,我們總結(jié)為三個(gè)流程:

1.bumpServiceExecutingLocked,啟動(dòng)超時(shí)檢查。

2.thread.scheduleCreateService通知APP一側(cè)去創(chuàng)建Service。

3.sendServiceArgsLocked通知APP執(zhí)行Service的生命流程。

private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,
            IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,
            boolean enqueueOomAdj) throws RemoteException {
        //1.啟動(dòng)超時(shí)檢查
        bumpServiceExecutingLocked(r, execInFg, "create", null /* oomAdjReason */);
        ...
        //2.通知APP創(chuàng)建service
            thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),
                    app.mState.getReportedProcState());
            r.postNotification();
            created = true;
        ...
        //3.通知執(zhí)行service生命流程
        sendServiceArgsLocked(r, execInFg, true);
       ...
    }

三.系統(tǒng)側(cè)通知APP啟動(dòng)Service

一般情況下,APP側(cè)會(huì)收到系統(tǒng)側(cè)發(fā)過來兩種類型的通知,

第一種:創(chuàng)建Service的任務(wù)通知

第二種:執(zhí)行Service生命流程的通知,通知Service執(zhí)行onStartCommand方法。

ApplicationThread接受通知并創(chuàng)建Service

系統(tǒng)側(cè)持有APP側(cè)的binder,會(huì)通過scheduleCreateService這個(gè)binder方法通知APP一側(cè)進(jìn)行相應(yīng)的操作。而APP側(cè),完成這個(gè)工作接收的就是ApplicationThread中的scheduleCreateService方法。該方法收到通知后,通過handler切換到主線程處理:

 public final void scheduleCreateService(IBinder token,
                ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
            updateProcessState(processState, false);
            CreateServiceData s = new CreateServiceData();
            s.token = token;
            s.info = info;
            s.compatInfo = compatInfo;
            sendMessage(H.CREATE_SERVICE, s);
        }

handle中,會(huì)切換到主線程執(zhí)行ActivityThread的handleCreateService方法。

主要執(zhí)行了如下的幾段邏輯:

1.如果是首次創(chuàng)建App進(jìn)程的話,則需要重新創(chuàng)建Application;

2.創(chuàng)建Service對(duì)象;

3.調(diào)用service的attach方法進(jìn)行關(guān)聯(lián);

4.調(diào)用service的onCreate生命周期方法;

5.創(chuàng)建完成后,通過serviceDoneExecuting通知系統(tǒng)側(cè)創(chuàng)建完成。

try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
            Application app = packageInfo.makeApplication(false, mInstrumentation);
            final java.lang.ClassLoader cl;
            if (data.info.splitName != null) {
                cl = packageInfo.getSplitClassLoader(data.info.splitName);
            } else {
                cl = packageInfo.getClassLoader();
            }
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
            ContextImpl context = ContextImpl.getImpl(service
                    .createServiceBaseContext(this, packageInfo));
            if (data.info.splitName != null) {
                context = (ContextImpl) context.createContextForSplit(data.info.splitName);
            }
            if (data.info.attributionTags != null && data.info.attributionTags.length > 0) {
                final String attributionTag = data.info.attributionTags[0];
                context = (ContextImpl) context.createAttributionContext(attributionTag);
            }
            // Service resources must be initialized with the same loaders as the application
            // context.
            context.getResources().addLoaders(
                    app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
            context.setOuterContext(service);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            service.onCreate();
            mServicesData.put(data.token, data);
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

ApplicationThread接受通知并執(zhí)行Service的生命流程

同樣的,這里完成接受的是,仍然是ApplicationThread中的方法。這個(gè)流程中的接受方法是scheduleServiceArgs方法。

ApplicationThread中,收到通知后,通過handler把任務(wù)轉(zhuǎn)交到主線程。

 public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
            List<ServiceStartArgs> list = args.getList();
            for (int i = 0; i < list.size(); i++) {
                ServiceStartArgs ssa = list.get(i);
                ServiceArgsData s = new ServiceArgsData();
                s.token = token;
                s.taskRemoved = ssa.taskRemoved;
                s.startId = ssa.startId;
                s.flags = ssa.flags;
                s.args = ssa.args;
                sendMessage(H.SERVICE_ARGS, s);
            }
        }

接下來handler中切換到主線程會(huì)執(zhí)行ActivityThread的handleServiceArgs方法。

handleServiceArgs方法主要會(huì)完成以下幾件事:

1.找到對(duì)應(yīng)的service,調(diào)用起onStartCommand方法;

2.通知系統(tǒng)側(cè)回調(diào)完成。

private void handleServiceArgs(ServiceArgsData data) {
        CreateServiceData createData = mServicesData.get(data.token);
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                if (data.args != null) {
                    data.args.setExtrasClassLoader(s.getClassLoader());
                    data.args.prepareToEnterProcess(isProtectedComponent(createData.info),
                            s.getAttributionSource());
                }
                int res;
                if (!data.taskRemoved) {
                    res = s.onStartCommand(data.args, data.flags, data.startId);
                } else {
                    s.onTaskRemoved(data.args);
                    res = Service.START_TASK_REMOVED_COMPLETE;
                }
                QueuedWork.waitToFinish();
                try {
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to start service " + s
                            + " with " + data.args + ": " + e.toString(), e);
                }
            }
        }
    }

發(fā)我們發(fā)現(xiàn),不論是創(chuàng)建service,還是通知執(zhí)行service的生命流程,最終都執(zhí)行了一個(gè)完成的通知,這有何意圖呢?是的,這個(gè)意圖就是和ANR相關(guān)的,我們下一章來講了。

四.總結(jié)

前面一一講了實(shí)現(xiàn)的原理,我們最后再來做一個(gè)總結(jié),盡量用一張圖+幾句話的方式來概括。

1.無論前臺(tái)啟動(dòng)還是后臺(tái)啟動(dòng),最終都會(huì)走到ContextImpl這個(gè)最終實(shí)現(xiàn)類中的方法,完成和AMS的交互。

2.AMS中主要是ActiveServices完成的整個(gè)流程。其核心方法是realStartServiceLocked。

他首先啟動(dòng)一個(gè)延時(shí)消息,通過延時(shí)消息進(jìn)行超時(shí)的監(jiān)測。

然后通知APP去生成Service。

通知APP側(cè)去完成Service的生命周期流程onStartCommand。

3.收到APP側(cè)執(zhí)行完成的通知后,則取消注冊(cè)延時(shí)消息。

到此這篇關(guān)于Android Service完整實(shí)現(xiàn)流程分析的文章就介紹到這了,更多相關(guān)Android Service內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android微信Tinker熱更新詳細(xì)使用

    Android微信Tinker熱更新詳細(xì)使用

    這篇文章主要介紹了Android微信Tinker熱更新的詳細(xì)使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android 5.0以上Toast不顯示的解決方法

    Android 5.0以上Toast不顯示的解決方法

    最近在開發(fā)中我們經(jīng)常會(huì)在適配5.0以后的機(jī)型遇到各種各樣的問題,其中有一個(gè)不大不小的問題就是:Toast不顯示問題,這篇文章就給大家總結(jié)了Android 5.0以上Toast不顯示的原因與解決方法,有需要的朋友們可以參考借鑒,下面來一起看看吧。
    2016-11-11
  • Android評(píng)分RationBar控件使用詳解

    Android評(píng)分RationBar控件使用詳解

    這篇文章主要為大家詳細(xì)介紹了Android評(píng)分RationBar控件的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Android使用個(gè)推實(shí)現(xiàn)三方應(yīng)用的推送功能

    Android使用個(gè)推實(shí)現(xiàn)三方應(yīng)用的推送功能

    這篇文章主要為大家詳細(xì)介紹了Android使用個(gè)推實(shí)現(xiàn)三方應(yīng)用的推送功能,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Android之頭像圖片變圓形顯示

    Android之頭像圖片變圓形顯示

    本文主要介紹了Android中頭像圖片變圓形的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-04-04
  • Android錄音播放管理工具

    Android錄音播放管理工具

    這篇文章主要為大家詳細(xì)介紹了Android錄音播放管理工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • 安卓11適配攻略搶先看

    安卓11適配攻略搶先看

    這篇文章主要介紹了安卓11適配攻略搶先看,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • MobLink?Android?快速集成指南

    MobLink?Android?快速集成指南

    這篇文章主要為大家介紹了MobLink?Android?快速集成指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • Android Retrofit文件下載進(jìn)度顯示問題的解決方法

    Android Retrofit文件下載進(jìn)度顯示問題的解決方法

    這篇文章主要為大家詳細(xì)介紹了Android Retrofit文件下載進(jìn)度顯示問題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android實(shí)現(xiàn)一鍵鎖屏功能

    Android實(shí)現(xiàn)一鍵鎖屏功能

    這篇文章主要介紹了Android實(shí)現(xiàn)一鍵鎖屏,在xml中創(chuàng)建device_admin.xml,在manifest中加入詳細(xì)文件,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10

最新評(píng)論