本文是探索Activity启动源码的第二篇, 其余参考第一篇.

Activity

第一篇的流程图:

流程图

第一篇已经探索至关键位置, 即ActivityStackSupervisor的realStartActivityLocked方法, 方法如其名, 从此开始, 才是真正地(Real)启动(Start). Let's start!


ActivityManagerService

ActivityStackSupervisor#realStartActivityLocked:

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException{// 当屏幕方向修改时, 推迟恢复, 防止冗余启动Activity.if (checkConfig) {Configuration config = mWindowManager.updateOrientationFromAppTokens(mService.mConfiguration,r.mayFreezeScreenLocked(app) ? r.appToken : null);mService.updateConfigurationLocked(config, r, false, true /* deferResume */);}// 将进程描述符(ProcessRecord)设置入Activity描述符(ActivityRecord)r.app = app;app.waitingToKill = null; // 避免在后台被杀死r.launchCount++; // 增加启动次数r.lastLaunchTime = SystemClock.uptimeMillis(); // 最新启动时间// 当Activity描述符不在进程的Activity列表中, 将Activity添加入进程的Activity列表int idx = app.activities.indexOf(r);if (idx < 0) {app.activities.add(r);}// AMS更新进程描述符为最少最新使用(LRU).mService.updateLruProcessLocked(app, true, null); // ...try {// ...// 远程调用ApplicationThread的scheduleLaunchActivityapp.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);// ...} catch (RemoteException e) {// ...}// ...return true;
}

ActivityRecord即Activity描述符(变量r), 含有被启动的Activity信息; ProcessRecord即进程描述符(变量app), 含有当前应用的进程信息.
app.thread类型是IApplicationThread, 通过IApplicationThread的代理ApplicationThreadProxy, 远程调用ApplicationThread的scheduleLaunchActivity方法, ApplicationThread是IApplicationThread的最终实现.

启动Activity再次AMS(ActivityManagerService)通过远程调用(Binder)交给应用进程(ActivityThread)处理. ApplicationThread是ActivityThread的私有类.

ApplicationThread#scheduleLaunchActivity:

@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,ActivityInfo info, Configuration curConfig, Configuration overrideConfig,CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,int procState, Bundle state, PersistableBundle persistentState,List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,boolean notResumed, boolean isForward, ProfilerInfo profilerInfo){// ...// 即来自客户端(AMS)的Activity描述符ActivityClientRecord r = new ActivityClientRecord();// 将AMS的Activity描述符, 转换为当前进程的Activity描述符r.token = token;// ...// 封装, 发送启动消息给H类处理, 并传递Activity描述符sendMessage(H.LAUNCH_ACTIVITY, r);
}

sendMessage是重载方法, 最终调用H类处理数据.

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async){// ...// 最终由H类(Handler)处理数据mH.sendMessage(msg);
}

将启动Activity交给ActivityThread的Handler H类处理.

private class H extends Handler{public void handleMessage(Message msg){switch (msg.what) {case LAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");ActivityClientRecord r = (ActivityClientRecord)msg.obj;// 设置Activity描述符的包信息r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);// 至此, 完成启动Activity已经由AMS交给当前应用, 在当前应用中启动Activity.handleLaunchActivity(r, null);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);} break;}}
}

启动Activity, 先由当前进程, 通过ActivityManagerNative#getDefault#startActivity方法, 交给AMS处理, AMS管理Activity的Stack和Task, 并设置Activity描述符(Record); 再通过app.thread#scheduleLaunchActivity方法, 继续交给当前进程处理.

AMS切换当前线程的流程图:

流程图


ActivityThread

ActivityThread#handleLaunchActivity:

handleLaunchActivity调用performLaunchActivity方法, 继续执行启动, 在成功后, 调用handleResumeActivity方法, 执行显示Activity.

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason){// 因为当前进程正在活跃, 所以跳过在后台中执行GC.unscheduleGcIdler();// ...// 确保使用最近的环境配置handleConfigurationChanged(null, null);if (localLOGV) Slog.v(TAG, "Handling launch of " + r);// 在创建Activity前, 初始化WindowManagerGlobal, 即WindowManagerServiceWindowManagerGlobal.initialize();// 执行启动ActivityActivity a = performLaunchActivity(r, customIntent);// 在启动成功后, 处理恢复Activityif (a != null) {r.createdConfig = new Configuration(mConfiguration);reportSizeConfigurations(r);Bundle oldState = r.state;// 恢复ActivityhandleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);// ...}} else {// 如果发生错误, 则AMS停止启动Activitytry {ActivityManagerNative.getDefault().finishActivity(r.token, Activity.RESULT_CANCELED, null,Activity.DONT_FINISH_TASK_WITH_ACTIVITY);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}}}

ActivityThread#performLaunchActivity:

performLaunchActivity方法是Activity启动的核心:

  1. 获取Activity的组件信息(ComponentName);
  2. 根据组件使用反射创建Activity(newActivity);
  3. 将Activity绑定(attach)Application和BaseContext;
  4. 相继调用onCreate, onStart, onRestoreInstanceState, onPostCreate等方法.
  5. 放入Activity列表(Map)中统一管理, token是key.
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {ActivityInfo aInfo = r.activityInfo;if (r.packageInfo == null) {// 通过应用信息, 兼容信息, 从PMS, 获取Activity的包信息r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,Context.CONTEXT_INCLUDE_CODE);}// 获取组件信息ComponentName component = r.intent.getComponent();if (component == null) {component = r.intent.resolveActivity(mInitialApplication.getPackageManager());r.intent.setComponent(component);}// 当指定Activity时, 使用包名和类名创建组件if (r.activityInfo.targetActivity != null) {component = new ComponentName(r.activityInfo.packageName,r.activityInfo.targetActivity);}Activity activity = null;try {java.lang.ClassLoader cl = r.packageInfo.getClassLoader();// 通过反射, 使用ClassLoader创建Activityactivity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);// ...} catch (Exception e) {// ...}try {// 使用单例模式, 创建ApplicationApplication app = r.packageInfo.makeApplication(false, mInstrumentation);// ...if (activity != null) {// 创建Activity的上下文BaseContextContext appContext = createBaseContextForActivity(r, activity);// ...// 将Activity绑定上下文appContext, 和应用appactivity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window);// ...// 设置主题int theme = r.activityInfo.getThemeResource();if (theme != 0) {activity.setTheme(theme);}activity.mCalled = false; // 判断执行是否成功, 成功会置true// 调用Activity的onCreate方法.if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}// ...// 调用Activity的onStart方法.if (!r.activity.mFinished) {activity.performStart();r.stopped = false;}// 调用Activity的onRestoreInstanceState方法.if (!r.activity.mFinished) {if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}// 调用Activity的onPostCreate方法.if (!r.activity.mFinished) {activity.mCalled = false; // 判断执行是否成功, 成功会置trueif (r.isPersistable()) {mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnPostCreate(activity, r.state);}// ...}}r.paused = true;// 将Activity放入ActivityThread的Activity数组中统一管理.mActivities.put(r.token, r);} // ...return activity;
}

onPostCreate: Called when activity start-up is complete (after onStart() and onRestoreInstanceState(Bundle) have been called). Applications will generally not implement this method; it is intended for system classes to do final initialization after application code has run.
在调用时, 表明Activity已经完全启动, 只剩下显示(onResume).

通过分析performLaunchActivity, 我们也更加清晰Activity的生命周期, 顺序如下, onCreate, onStart, onRestoreInstanceState, onPostCreate. 注意, onStart是Activity处理; 其余三个是Instrumentation处理, 支持继承重写相应方法, 自行处理.


至此, Activity已经完全启动, 并调用相应的生命周期方法.

OK, that's all! Enjoy it!

原文地址: http://www.jianshu.com/p/574d7d3fa34f

探索7.x, 全面解析Activity启动框架 (2)相关推荐

  1. 探索7.x, 全面解析Activity启动框架 (1)

    无论怎么说, Activity都是Android最核心的组件, 主要负责向用户展示应用信息. Activity的生命周期由Android系统控制, 启动与绘制都是自动完成. 对于开发人员而言, 仅仅是 ...

  2. android activity启动流程_1307页!一线大厂Android面试全套真题解析!

    /   前言   / 金九银十到了,很多读者都反映有面试的需求,所以我特地给大家准备了一点资料! 下面的题目都是大家在面试一线互联网大厂时经常遇到的面试真题和答案解析,如果大家还有其他好的题目或者好的 ...

  3. 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 二 | AMS 进程相关源码 | 主进程相关源码 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  4. html获取此次点击的id,github项目解析(八)--Activity启动过程中获取组件宽高的三种方式...

    转载请标明出处:1片枫叶的专栏 上1个github小项目中我们介绍了避免按钮重复点击的小框架,其实现的核心逻辑是重写OnClickListener的onClick方法,添加避免重复点击的逻辑,即为第2 ...

  5. 【Android 插件化】Hook 插件化框架总结 ( 插件包管理 | Hook Activity 启动流程 | Hook 插件包资源加载 ) ★★★

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  6. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  7. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | AMS 启动前使用动态代理替换掉插件 Activity 类 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  8. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 反射获取 IActivityManager 对象 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  9. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | Hook 点分析 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

最新文章

  1. 设计模式 — 结构型模式 — 代理模式
  2. java tomcat 时间不对解决办法
  3. systemd教程推荐
  4. bootstrap 单选按钮点击change事件 只触发一次_微信支付新增“确认”按钮,付错钱将成为历史?...
  5. 计算机硬件选型报价,组装电脑硬件该怎么选择?这几个硬件要舍得花钱,千万别买错了!...
  6. julia常用矩阵函数_Julia系列教程3 数学运算 矩阵运算
  7. 计算机windows10属性配置,电脑显示属性设置,教你win10系统电脑显示属性的设置教程...
  8. Array with Odd Sum(CF-1296A)
  9. Datepicker-for-Bootstrap 日期选择插件
  10. 新能源车为什么不加变速箱解决高速高耗电的问题?
  11. 特斯拉要用太阳能满足整座岛全年能源需求
  12. 使用python下载文件_利用python web框架做文件流下载
  13. Linux文件上传下载sz 和 rz 命令
  14. react中IOS手机里面两个input同时存在时,聚焦focus失效解决办法
  15. WARN No appenders could be found for logger的解决方法
  16. tomcat 设置session过期时间(四种方式)
  17. 一张图了解CAS单点登录的流程
  18. 计算机专业毕业论文谢辞,计算机毕业论文谢辞模板(精选模板三篇)
  19. 读史使人明智,二混子带你漫画学历史~
  20. Star-GAN阅读笔记

热门文章

  1. MYSQL自定义排序
  2. R: ggplot2(1)
  3. 【Windows10下OpenCV 3.4.0 + Visual Studio 2015开发环境的配】
  4. 科大星云诗社动态20210815
  5. [C++调试笔记]求电势posi.cpp
  6. GitHub如何下载单个文件夹
  7. TypeError: 'function' object is not subscriptable
  8. oracle数据库在sqlplus登录时遇到的问题
  9. jsp可以使用iframe_使用 JavaScript object URLs,可以处理图像、音频和视频
  10. 运动目标检测_单高斯背景建模