startService啟動流程---Service在App程序但未啟動
阿新 • • 發佈:2019-01-27
在Service啟動流程(startService)的最後,分析了在呼叫startService時可能存在的三種情況,本文分析第二種情況—Service與App在同一個程序,但未啟動。
Service啟動流程(startService)最後已經說明,在這種情況下,系統會執行realStartServiceLocked
函式。
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app) throws RemoteException { ...... r.app = app; r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); app.services.add(r); bumpServiceExecutingLocked(r, "create"); updateLruProcessLocked(app, true, true); boolean created = false; try { ...... //跨程序去執行Service例項的建立 app.thread.scheduleCreateService(r, r.serviceInfo, compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo)); r.postNotification(); created = true; } finally { if (!created) { app.services.remove(r); scheduleServiceRestartLocked(r, false); } } ...... //Service建立完成後,執行onStartCommand函式 sendServiceArgsLocked(r, true); }
函式的邏輯還是比較清晰的,完成的工作主要有兩個:
- 建立Service例項
- 執行onStartCommand方法
接下來就來看下這兩個任務時如何完成的。
建立Service例項是一個Binder跨程序呼叫,Binder細節就不分析,直接進入ActivityThread檢視scheduleCreateService
的實現
public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo) { CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; queueOrSendMessage(H.CREATE_SERVICE, s); }
好吧,queueOrSendMessage
這個函式我們在ActivityThread中已經看到過很多次呼叫很多次了,我們直接進入到真正執行建立Service例項的函式queueOrSendMessage
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. ...... LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { //反射建立Service例項 java.lang.ClassLoader cl = packageInfo.getClassLoader(); service = (Service) cl.loadClass(data.info.name).newInstance(); } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to instantiate service " + data.info.name + ": " + e.toString(), e); } } try { ...... ContextImpl context = new ContextImpl(); context.init(packageInfo, null, this); Application app = packageInfo.makeApplication(false, mInstrumentation); context.setOuterContext(service); service.attach(context, this, data.info.name, data.token, app, ActivityManagerNative.getDefault()); //執行Service onCreate方法 service.onCreate(); mServices.put(data.token, service); try { //通知ActivityManagerService例項建立完成 ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, 0, 0, 0); } catch (RemoteException e) { // nothing to do. } } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } }
函式的程式碼不短也不長,還是比較好理解的。首先獲取Service的資訊,然後呼叫反射建立Service例項(想想Activity例項的建立,是不是也是反射?),建立完例項後就會去執行attach方法,執行完attach方法後就會去執行onCreate方法(想想Activity,是不是也是先執行attach在執行onCreate?),執行完onCreate方法後,通知ActivityManagerService。
執行完Service例項的建立,接下來執行onStartCommand
的流程就是 startService啟動流程—Service已經啟動中描述的流程,我就不再分析了。