《转》深入理解Activity启动流程(三)–Activity启动的详细流程2
本文原创作者:Cloud Chou. 出处:本文链接
本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究。
- 深入理解Activity启动流程(一)--Activity启动的概要流程
- 深入理解Activity启动流程(二)--Activity启动相关类的类图
- 深入理解Activity启动流程(三)--Activity启动的详细流程1
- 深入理解Activity启动流程(四)--Activity Task的调度算法
上篇博客介绍了Activity详细启动流程的前半部分:
- 1. Activity调用ActivityManagerService启动应用
- 2. ActivityManagerService调用Zygote孵化应用进程
- 3. Zygote孵化应用进程
本篇博客主要介绍Activity详细启动流程的后半部分:
- 4. 新进程启动ActivityThread
- 5. 应用进程绑定到ActivityManagerService
- 6. ActivityThread的Handler处理启动Activity的消息
4. 新进程启动ActivityThread
点击图片可看大图
Zygote进程孵化出新的应用进程后,会执行ActivityThread类的main方法。在该方法里会先准备好Looper和消息队列,然后调用attach方法将应用进程绑定到ActivityManagerService,然后进入loop循环,不断地读取消息队列里的消息,并分发消息。
//ActivityThread类 public static void main(String[] args) { //... Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } AsyncTask.init(); //... Looper.loop(); //... }
5. 应用进程绑定到ActivityManagerService
点击图片可看大图
在ActivityThread的main方法里调用thread.attach(false);attach方法的主要代码如下所示:
//ActivityThread类 private void attach(boolean system) { sThreadLocal.set(this); mSystemThread = system; if (!system) { //... IActivityManager mgr = ActivityManagerNative.getDefault(); try { //调用ActivityManagerService的attachApplication方法 //将ApplicationThread对象绑定至ActivityManagerService, //这样ActivityManagerService就可以 //通过ApplicationThread代理对象控制应用进程 mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } } else { //... } //... }
ActivityManagerService的attachApplication方法执行attachApplicationLocked(thread, callingPid)进行绑定。
//ActivityManagerService类 private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { ProcessRecord app; //... app.thread = thread; //... try { //... thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profileFile, profileFd, profileAutoStop, app.instrumentationArguments, app.instrumentationWatcher, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(), mCoreSettingsObserver.getCoreSettingsLocked()); //... } catch (Exception e) { //... } //... ActivityRecord hr = mMainStack.topRunningActivityLocked(null); if (hr != null && normalMode) { if (hr.app == null && app.uid == hr.info.applicationInfo.uid && processName.equals(hr.processName)) { try { if (mHeadless) { Slog.e(TAG, "Starting activities not supported on headless device: " + hr); } else if (mMainStack.realStartActivityLocked(hr, app, true, true)) { //mMainStack.realStartActivityLocked真正启动activity didSomething = true; } } catch (Exception e) { //... } } else { //... } } //... return true; }
attachApplicationLocked方法有两个重要的函数调用thread.bindApplication和mMainStack.realStartActivityLocked。thread.bindApplication将应用进程的ApplicationThread对象绑定到ActivityManagerService,也就是说获得ApplicationThread对象的代理对象。mMainStack.realStartActivityLocked通知应用进程启动Activity。
5.1 thread.bindApplication
thread对象其实是ActivityThread里ApplicationThread对象在ActivityManagerService的代理对象,故此执行thread.bindApplication,最终会调用ApplicationThread的bindApplication方法,该方法的主要代码如下所示:
//ActivityThread类 public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) { //... AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.debugMode = debugMode; data.enableOpenGlTrace = enableOpenGlTrace; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfileFile = profileFile; data.initProfileFd = profileFd; data.initAutoStopProfiler = false; queueOrSendMessage(H.BIND_APPLICATION, data); }
这样调用queueOrSendMessage会往ActivityThread的消息队列发送消息,消息的用途是BIND_APPLICATION。
这样会在handler里处理BIND_APPLICATION消息,接着调用handleBindApplication方法处理绑定消息。
//ActivityThread类 private void handleBindApplication(AppBindData data) { //... ApplicationInfo instrApp = new ApplicationInfo(); instrApp.packageName = ii.packageName; instrApp.sourceDir = ii.sourceDir; instrApp.publicSourceDir = ii.publicSourceDir; instrApp.dataDir = ii.dataDir; instrApp.nativeLibraryDir = ii.nativeLibraryDir; LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, appContext.getClassLoader(), false, true); ContextImpl instrContext = new ContextImpl(); instrContext.init(pi, null, this); //... if (data.instrumentationName != null) { //... } else { //注意Activity的所有生命周期方法都会被Instrumentation对象所监控, //也就说执行Activity的生命周期方法前后一定会调用Instrumentation对象的相关方法 //并不是说只有跑单测用例才会建立Instrumentation对象, //即使不跑单测也会建立Instrumentation对象 mInstrumentation = new Instrumentation(); } //... try { //... Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; //... try { mInstrumentation.onCreate(data.instrumentationArgs); }catch (Exception e) { //... } try { //这里会调用Application的onCreate方法 //故此Applcation对象的onCreate方法会比ActivityThread的main方法后调用 //但是会比这个应用的所有activity先调用 mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { //... } } finally { StrictMode.setThreadPolicy(savedPolicy); } }
5.2 mMainStack.realStartActivityLocked
realStartActivity会调用scheduleLaunchActivity启动activity,主要代码:
//ActivityStack类 final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { //... try { //... app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, r.icicle, results, newIntents, !andResume, mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop); //... } catch (RemoteException e) { //... } //... return true; }
同样app.thread也只是ApplicationThread对象在ActivityManagerService的一个代理对象而已,最终会调用ApplicationThread的scheduleLaunchActivity方法。
//ActivityThread类 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo, Bundle state, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward, String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) { ActivityClientRecord r = new ActivityClientRecord(); r.token = token; r.ident = ident; r.intent = intent; r.activityInfo = info; r.compatInfo = compatInfo; r.state = state; r.pendingResults = pendingResults; r.pendingIntents = pendingNewIntents; r.startsNotResumed = notResumed; r.isForward = isForward; r.profileFile = profileName; r.profileFd = profileFd; r.autoStopProfiler = autoStopProfiler; updatePendingConfiguration(curConfig); queueOrSendMessage(H.LAUNCH_ACTIVITY, r); }
这里调用了queueOrSendMessage往ActivityThread的消息队列发送了消息,消息的用途是启动Activity,接下来ActivityThread的handler便会处理该消息。
6. ActivityThread的Handler处理启动Activity的消息
点击图片可看大图
ActivityThread的handler调用handleLaunchActivity处理启动Activity的消息,handleLaunchActivity的主要代码如下所示:
//ActivityThread类 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { //... Activity a = performLaunchActivity(r, customIntent); if (a != null) { //... handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed); //... } else { //... } }
handleLaunchActivity方法里有有两个重要的函数调用,performLaunchActivity和handleResumeActivity,performLaunchActivity会调用Activity的onCreate,onStart,onResotreInstanceState方法,handleResumeActivity会调用Activity的onResume方法.
6.1 performLaunchActivity
performLaunchActivity的主要代码如下所示:
//ActivityThread类 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { //... Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); //... } catch (Exception e) { //... } try { //r.packageInfo.makeApplication实际并未创建Application对象, //因为bindApplication过程已经创建了Application对象, //makeApplication方法会返回已创建的Application对象 Application app = r.packageInfo.makeApplication(false, mInstrumentation); //... if (activity != null) { //... //将application对象,appContext对象绑定到新建的activity对象 activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config); //... //会调用Activity的onCreate方法 mInstrumentation.callActivityOnCreate(activity, r.state); //... //... //调用Activity的onStart方法 if (!r.activity.mFinished) { activity.performStart(); r.stopped = false; } if (!r.activity.mFinished) { if (r.state != null) { //会调用Activity的onRestoreInstanceState方法 mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } } if (!r.activity.mFinished) { activity.mCalled = false; mInstrumentation.callActivityOnPostCreate(activity, r.state); //... } } //... } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { //... } return activity; }
6.2 handleResumeActivity
handleResumeActivity的主要代码如下所示:
//ActivityThread类 final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) { //... //performResumeActivity最终会调用Activity的onResume方法 ActivityClientRecord r = performResumeActivity(token, clearHide); if (r != null) { final Activity a = r.activity; //... //显示界面 if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (a.mVisibleFromClient) { a.mWindowAdded = true; wm.addView(decor, l); } //... } else if (!willBeVisible) { //... } // Tell the activity manager we have resumed. if (reallyResume) { try { ActivityManagerNative.getDefault().activityResumed(token); } catch (RemoteException ex) { } } } else { //... } }
performResumeActivity的主要代码如下所示:
//ActivityThread类 public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide) { ActivityClientRecord r = mActivities.get(token); //... if (r != null && !r.activity.mFinished) { //... try { //... //会调用Activity的onResume方法 r.activity.performResume(); //... } catch (Exception e) { //... } } return r; }
总结
Activity的概要启动流程:
用户在Launcher程序里点击应用图标时,会通知ActivityManagerService启动应用的入口Activity,ActivityManagerService发现这个应用还未启动,则会通知Zygote进程孵化出应用进程,然后在这个dalvik应用进程里执行ActivityThread的main方法。应用进程接下来通知ActivityManagerService应用进程已启动,ActivityManagerService保存应用进程的一个代理对象,这样ActivityManagerService可以通过这个代理对象控制应用进程,然后ActivityManagerService通知应用进程创建入口Activity的实例,并执行它的生命周期方法
现在也可以理解:
如果应用的组件(包括所有组件Activity,Service,ContentProvider,Receiver) 被启动,肯定会先启动以应用包名为进程名的进程,这些组件都会运行在应用包名为进程名的进程里,并且是在主线程里。应用进程启动时会先创建Application对象,并执行Application对象的生命周期方法,然后才启动应用的组件。
有一种情况比较特殊,那就是为组件设置了特殊的进程名,也就是说通过android:process设置进程名的情况,此时组件运行在单独的进程内。
下篇博客将介绍Activity,Task的调度算法。