




已閱讀5頁(yè),還剩6頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Android Service的啟動(dòng)過(guò)程剛開始學(xué)習(xí)Service的時(shí)候以為它是一個(gè)線程的封裝,也可以執(zhí)行耗時(shí)操作。其實(shí)不然,Service是運(yùn)行在主線程的。直接執(zhí)行耗時(shí)操作是會(huì)阻塞主線程的。長(zhǎng)時(shí)間就直接ANR了。我們知道Service可以執(zhí)行一些后臺(tái)任務(wù),是后臺(tái)任務(wù)不是耗時(shí)的任務(wù),后臺(tái)和耗時(shí)是有區(qū)別的喔。 這樣就很容易想到音樂(lè)播放器,天氣預(yù)報(bào)這些應(yīng)用是要用到Service的。當(dāng)然如果要在Service中執(zhí)行耗時(shí)操作的話,開個(gè)線程就可以了。關(guān)于Service的運(yùn)行狀態(tài)有兩種,啟動(dòng)狀態(tài)和綁定狀態(tài),兩種狀態(tài)可以一起。 啟動(dòng)一個(gè)Service只需調(diào)用Context的startService方法,傳進(jìn)一個(gè)Intent即可??雌饋?lái)好像很簡(jiǎn)單的說(shuō),那是因?yàn)锳ndroid為了方便開發(fā)者,做了很大程度的封裝。那么你真的有去學(xué)習(xí)過(guò)Service是怎么啟動(dòng)的嗎?Service的onCreate方法回調(diào)前都做了哪些準(zhǔn)備工作?先上一張圖大致了解下,灰色背景框起來(lái)的是同一個(gè)類中的方法,如下圖:那接下來(lái)就從源碼的角度來(lái)分析Service的啟動(dòng)過(guò)程。當(dāng)然是從Context的startService方法開始,Context的實(shí)現(xiàn)類是ContextImpl,那么我們就看到ContextImpl的startService方法即可,如下:Overridepublic ComponentName startService(Intent service) warnIfCallingFromSystemProcess(); return startServiceCommon(service, mUser);會(huì)轉(zhuǎn)到startServiceCommon方法,那跟進(jìn)startServiceCommon方法方法瞧瞧。private ComponentName startServiceCommon(Intent service, UserHandle user) try validateServiceIntent(service); service.prepareToLeaveProcess(); ComponentName cn = ActivityManagerNative.getDefault().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver(), getOpPackageName(), user.getIdentifier(); /代碼省略 return cn; catch (RemoteException e) throw new RuntimeException(Failure from system, e); 可以看到調(diào)用了ActivityManagerNative.getDefault()的startService方法來(lái)啟動(dòng)Service,ActivityManagerNative.getDefault()是ActivityManagerService,簡(jiǎn)稱AMS。那么現(xiàn)在啟動(dòng)Service的過(guò)程就轉(zhuǎn)移到了ActivityManagerService,我們關(guān)注ActivityManagerService的startService方法即可,如下:Overridepublic ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId) throws TransactionTooLargeException /代碼省略 synchronized(this) final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, callingPackage, userId); Binder.restoreCallingIdentity(origId); return res; 在上述的代碼中,調(diào)用了ActiveServices的startServiceLocked方法,那么現(xiàn)在Service的啟動(dòng)過(guò)程從AMS轉(zhuǎn)移到了ActiveServices了。繼續(xù)跟進(jìn)ActiveServices的startServiceLocked方法,如下:ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, String callingPackage, int userId) throws TransactionTooLargeException /代碼省略 ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg); /代碼省略 ServiceRecord r = res.record; /代碼省略 return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);在startServiceLocked方法中又會(huì)調(diào)用startServiceInnerLocked方法,我們瞧瞧startServiceInnerLocked方法,ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException ProcessStats.ServiceState stracker = r.getTracker(); if (stracker != null) stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); r.callStart = false; synchronized (r.stats.getBatteryStats() r.stats.startRunningLocked(); String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false); /代碼省略 return ;startServiceInnerLocked方法內(nèi)部調(diào)用了bringUpServiceLocked方法,此時(shí)啟動(dòng)過(guò)程已經(jīng)快要離開ActiveServices了。繼續(xù)看到bringUpServiceLocked方法。如下:private final String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting) throws TransactionTooLargeException /代碼省略 if (app != null & app.thread != null) try app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats); realStartServiceLocked(r, app, execInFg); return null; /代碼省略 return null;省略了大部分if判斷,相信眼尖的你一定發(fā)現(xiàn)了核心的方法,那就是 realStartServiceLocked,沒(méi)錯(cuò),看名字就像是真正啟動(dòng)Service。那么事不宜遲跟進(jìn)去探探吧。如下:private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException /代碼省略 boolean created = false; try /代碼省略 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); app.thread.scheduleCreateService(r, r.serviceInfo, mApatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); r.postNotification(); created = true; catch (DeadObjectException e) Slog.w(TAG, Application dead when creating service + r); mAm.appDiedLocked(app); throw e; /代碼省略 sendServiceArgsLocked(r, execInFg, true); /代碼省略找到了。app.thread調(diào)用了scheduleCreateService來(lái)啟動(dòng)Service,而app.thread是一個(gè)ApplicationThread,也是ActivityThread的內(nèi)部類。此時(shí)已經(jīng)到了主線程。 那么我們探探ApplicationThread的scheduleCreateService方法。如下:public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) updateProcessState(processState, false); CreateServiceData s = new CreateServiceData(); s.token = token; = info; patInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s);對(duì)待啟動(dòng)的Service組件信息進(jìn)行包裝,然后發(fā)送了一個(gè)消息。我們關(guān)注這個(gè)CREATE_SERVICE消息即可。public void handleMessage(Message msg) /代碼省略 case CREATE_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, serviceCreate); handleCreateService(CreateServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break; /代碼省略在handleMessage方法中接收到這個(gè)消息,然后調(diào)用了handleCreateService方法,跟進(jìn)handleCreateService探探究竟:private void handleCreateService(CreateServiceData data) / If we are getting ready to gc after going to the background, well / we are back active so skip it. unscheduleGcIdler(); LoadedApk packageInfo = getPackageInfoNoCheck( .applicationInfo, patInfo); Service service = null; try java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass().newInstance(); catch (Exception e) if (!mInstrumentation.onException(service, e) throw new RuntimeException( Unable to instantiate service + + : + e.toString(), e); try if (localLOGV) Slog.v(TAG, Creating service + ); ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); Application app = packageInfo.makeApplication(false, mInstrumentation); service.attach(context, this, , data.token, app, ActivityManagerNative.getDefault(); service.onCreate(); mServices.put(data.token, service); try ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); catch (RemoteException e) / nothing to do. catch (Exception e) if (!mInstrumentation.onException(service, e) throw new RuntimeException( Unable to create service + + : + e.toString(), e); 終于擊破,這個(gè)方法很核心的。一點(diǎn)點(diǎn)分析首先獲取到一個(gè)LoadedApk對(duì)象,在通過(guò)這個(gè)LoadedApk對(duì)象獲取到一個(gè)類加載器,通過(guò)這個(gè)類加載器來(lái)創(chuàng)建Service。如下:java.lang.ClassLoader cl = packageInfo.getClassLoader();service = (Service) cl.loadClass().newInstance();接著調(diào)用ContextImpl的createAppContext方法創(chuàng)建了一個(gè)ContextImpl對(duì)象。之后再調(diào)用LoadedApk的makeApplication方法來(lái)創(chuàng)建Application,這個(gè)創(chuàng)建過(guò)程如下:public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) if (mApplication != null) return mApplication; Application app = null; String appClass = mApplicationInfo.className; if (forceDefaultAppClass | (appClass = null) appClass = android.app.Application; try java.lang.ClassLoader cl = getClassLoader(); if (!mPackageName.equals(android) initializeJavaContextClassLoader(); ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext); appContext.setOuterContext(app); catch (Exception e) if (!mActivityThread.mInstrumentation.onException(app, e) throw new RuntimeException( Unable to instantiate application + appClass + : + e.toString(), e); mActivityThread.mAllApplications.add(app); mApplication = app; if (instrumentation != null) try instrumentation.callApplicationOnCreate(app); catch (Eception e) if (!instrumentation.onException(app, e) throw new RuntimeException( Unable to create application + app.getClass().getName() + : + e.toString(), e); / Rewrite the R constants for all library apks. SparseArray packageIdentifiers = getAssets(mActivityThread) .getAssignedPackageIdentifiers(); final int N = packageIdentifiers.size(); for (int i = 0; i N; i+) final int id = packageIdentifiers.keyAt(i); if (id = 0x01 | id = 0x7f) continue; rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id); return app;當(dāng)然Application是只有一個(gè)的,從上述代碼中也可以看出。在回來(lái)繼續(xù)看handleCreateService方法,之后service調(diào)用了attach方法關(guān)聯(lián)了ContextImpl和Application等最后service回調(diào)了onCreate方法,service.onCreate();mServices.put(data.token, service);并將這個(gè)service添加進(jìn)了一個(gè)了列表進(jìn)行管理。至此service啟動(dòng)了起來(lái),以上就是service的啟動(dòng)過(guò)程。你可能還想要知道onStartCommand方法是怎么被回調(diào)的?可能細(xì)心的你發(fā)現(xiàn)了在ActiveServices的realStartServiceLocked方法中,那里還有一個(gè)sendServiceArgsLocked方法。是的,那個(gè)就是入口。那么我們跟進(jìn)sendServiceArgsLocked方法看看onStartCommand方法是怎么回調(diào)的。private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg, boolean oomAdjusted) throws TransactionTooLargeException final int N = r.pendingStarts.size(); /代碼省略 try /代碼省略 r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, ent); catch (TransactionTooLargeException e) if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, Transaction too large: intent= + ent); caughtException = e; catch (RemoteException e) / Remote process gone. well let the normal cleanup take care of this. if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, Crashed while sending args: + r); caughtException = e; /代碼省略可以看到onStartCommand方法回調(diào)過(guò)程和onCreate方法的是很相似的,都會(huì)轉(zhuǎn)到app.thread。那么現(xiàn)在就跟進(jìn)ApplicationThread的scheduleServiceArgs。 你也可能猜到了應(yīng)該又是封裝一些Service的信息,然后發(fā)送一個(gè)消息, handleMessage接收。是的,源碼如下:public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId, int flags ,Intent args) ServiceArgsData s = new ServiceArgsData(); s.token = token; s.taskRemoved = taskRemoved; s.startId = startId; s.flags = flags; s.args = args; sendMessage(H.SERVICE_ARGS, s);public void handleMessage(Message msg) /代碼省略 case SERVICE_ARGS: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, serviceStart); handleServiceArgs(ServiceArgsData)m
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 小學(xué)一年級(jí)道德與法治課堂互動(dòng)教學(xué)計(jì)劃
- 2025-2030年中國(guó)電動(dòng)變焦一體化攝像機(jī)行業(yè)發(fā)展動(dòng)態(tài)及發(fā)展咨詢研究報(bào)告
- 2025-2030年中國(guó)電力環(huán)保設(shè)備境外融資報(bào)告
- 小學(xué)五年級(jí)閱讀推廣實(shí)踐活動(dòng)計(jì)劃
- 2025-2030年中國(guó)特種養(yǎng)殖動(dòng)物商業(yè)計(jì)劃書
- 2025-2030年中國(guó)海產(chǎn)品行業(yè)市場(chǎng)競(jìng)爭(zhēng)格局及投資可行性研究報(bào)告
- 2025-2030年中國(guó)汽車物流市場(chǎng)動(dòng)態(tài)調(diào)研與發(fā)展趨勢(shì)預(yù)測(cè)研究報(bào)告
- 2025-2030年中國(guó)汽車懸膠墊行業(yè)投資風(fēng)險(xiǎn)調(diào)研與投資潛力咨詢報(bào)告
- 2025-2030年中國(guó)水晶飾品市場(chǎng)銷售前景及運(yùn)行態(tài)勢(shì)研究報(bào)告
- 2025-2030年中國(guó)氨苯哌啶酮行業(yè)前景調(diào)查及未來(lái)風(fēng)險(xiǎn)評(píng)估報(bào)告
- 契稅補(bǔ)貼申請(qǐng)表
- 【汽車】上海大眾汽車有限公司——質(zhì)量保證部
- 西山煤電集團(tuán)白家莊礦煤層開采初步設(shè)計(jì)
- 魯班獎(jiǎng)迎檢分工細(xì)化
- 初中八年級(jí)體育與健康課教案(全冊(cè)).doc
- Q∕GDW 12100-2021 電力物聯(lián)網(wǎng)感知層技術(shù)導(dǎo)則
- 曲靖市中心城市綠地系統(tǒng)規(guī)劃20172035
- 最新金屬軟管設(shè)計(jì)制造新工藝新技術(shù)及性能測(cè)試實(shí)用手冊(cè)
- 小學(xué)生主格賓格表格說(shuō)明及練習(xí)
- 渠道項(xiàng)目報(bào)備管理規(guī)定
- 心理咨詢記錄--個(gè)案5
評(píng)論
0/150
提交評(píng)論