赞
踩
Activity栈中的一个节点,用于展示一个Activity
它集成了WindowToken实现了WindowManagerService中的一个接口
既然如此顺便看看WindowToken吧
用来替代ActivityStackSupervisor
这东西是ActivityThread中的一个变量
它可以作为一个测试框架的根基,因为它是先于我们的Application和Activity启动的,所以它可以监听到我们创建Activity和Application操作。
android是支持自定义Instrumentation的,可以通过继承Instrumentation重写里面的方法实现监听
顺手找了一篇参考文章:https://blog.csdn.net/weixin_42355665/article/details/117661233
最终会走到Instrumentation.execStartActivity方法
ActivityTaskManager.getService()返回结果就是IActivityTaskManager类型
需要说明的是本方法中最后一步调用的checkStartActivityResult方法可以根据返回的result判断启动activity的结果
checkStartActivityResult方法的实现可以查看 附1中内容
这里的ActivityTaskManager.getService()要说明一下,它最终调用到了ActivityTaskManager中的单例,然后获取binder调用接口
所以这里的ActivityTaskManager.getService().startActivity实际上就是ActivityTaskManagerService.startActivity
这里负责执行启动逻辑
代码巨长,关键代码在结尾处startActivityUnchecked
mService.getLifecycleManager().scheduleTransaction(clientTransaction)
实际类型是ApplicationThread.scheduleTransaction
mTransactionExecutor.execute(transaction);
createBaseContextForActivity方法的说明见:附2
下图中的newActivity用来创建Activity对象,实际上如果我们的Application如果没有创建,它会连带Application一起创建。但是似乎这个Application的创建并没有意义,只是个站位作用。
下图中appContext.setOuterContext(activity);方法,将我们的的activity对象赋值给ContextImpl,目的是让他们产生关联。
在Activity.attach方法中,只做了一件事,就是调用onAttachFragment方法来初始化Fragment
makeApplication方法的说明见附3
这个方法过后逻辑终于又转到了Activity中
本节参考:https://www.jianshu.com/p/e875f8bdedef
Activity启动过程,首先会调用startActivity,最终一定会调用到Activity.startActivityForResult方法。然后会调用Instrucment.execStartActivity方法并且会获取调用ActivityThread.getApplicationThread方法获取IApplicationThread对象,IApplicationThread是一个Binder对象,它是应用进程和atms沟通的桥梁。
调用完execStartActivity方法后,会获取atms实例,然后调用atms.startActivity方法,这就完成了应用和atms的通信,程序逻辑转换到了atms中。在atms进行一大堆操作后会调用IApplicationThread的方法回调到应用进程,执行activity页面的启动工作。
atms处理完成后会调用ApplicationThread.scheduleTransaction方法,因为IApplicationThread是一个Binder对象,所以这个方法将逻辑从atms中转回到应用逻辑中。
回到应用中处理的逻辑是这样的,首先通过ActivityThread.H发送一条handler消息,告诉主线程需要启动activity。最终会将逻辑调用到ActivityThread.handleLaunchActivity方法,在Instrumentaction中使用反射创建Activity对象实例,并调用Activity.attach方法,后面会再次调用到Instrumentation.callActivityOnCreate方法,从这里就进入了activity的生命周期了。
activity的启动过程一共有两次Binder通信,
- 用于进程调用ActivityTaskManagerService.startActivity,代码进入atms进程中执行
- ClientTransaction类中IApplicationThread.scheduleTransaction,atms调用应用进程的Binder让Activity启动逻辑回到应用进程
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public static void checkStartActivityResult(int res, Object intent) { if (!ActivityManager.isStartResultFatalError(res)) { return; } switch (res) { case ActivityManager.START_INTENT_NOT_RESOLVED: case ActivityManager.START_CLASS_NOT_FOUND: if (intent instanceof Intent && ((Intent)intent).getComponent() != null) throw new ActivityNotFoundException( "Unable to find explicit activity class " + ((Intent)intent).getComponent().toShortString() + "; have you declared this activity in your AndroidManifest.xml?"); throw new ActivityNotFoundException( "No Activity found to handle " + intent); case ActivityManager.START_PERMISSION_DENIED: throw new SecurityException("Not allowed to start activity " + intent); case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: throw new AndroidRuntimeException( "FORWARD_RESULT_FLAG used while also requesting a result"); case ActivityManager.START_NOT_ACTIVITY: throw new IllegalArgumentException( "PendingIntent is not an activity"); case ActivityManager.START_NOT_VOICE_COMPATIBLE: throw new SecurityException( "Starting under voice control not allowed for: " + intent); case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION: throw new IllegalStateException( "Session calling startVoiceActivity does not match active session"); case ActivityManager.START_VOICE_HIDDEN_SESSION: throw new IllegalStateException( "Cannot start voice activity on a hidden session"); case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION: throw new IllegalStateException( "Session calling startAssistantActivity does not match active session"); case ActivityManager.START_ASSISTANT_HIDDEN_SESSION: throw new IllegalStateException( "Cannot start assistant activity on a hidden session"); case ActivityManager.START_CANCELED: throw new AndroidRuntimeException("Activity could not be started for " + intent); default: throw new AndroidRuntimeException("Unknown error code " + res + " when starting " + intent); } }
![image.png](https://img-blog.csdnimg.cn/img_convert/ab059eb8f46d9f1335189bfd27ec876c.png#clientId=ub95fd704-f52b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=850&id=ucdf0e3a7&margin=[object Object]&name=image.png&originHeight=850&originWidth=1017&originalType=binary&ratio=1&rotation=0&showTitle=false&size=165332&status=done&style=none&taskId=u0fa31d6c-0f44-4251-aaca-32c5517b866&title=&width=1017)
makeApplication方法在LoadedApk中
下图中的mInstrumentation.newApplication是下面要看的重点
![image.png](https://img-blog.csdnimg.cn/img_convert/355935557472abb2bb1e54ef7f4d5236.png#clientId=ub95fd704-f52b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=870&id=u2c1b21ea&margin=[object Object]&name=image.png&originHeight=870&originWidth=801&originalType=binary&ratio=1&rotation=0&showTitle=false&size=143013&status=done&style=none&taskId=u5cfa2a40-7527-4da2-9cb2-98e58378e9f&title=&width=801)
这里的callApplicationOnCreate是下一步要看的重点
![image.png](https://img-blog.csdnimg.cn/img_convert/ff4d22179dcc2d81979a746f5114fae2.png#clientId=ub95fd704-f52b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=448&id=u17d54ac4&margin=[object Object]&name=image.png&originHeight=448&originWidth=643&originalType=binary&ratio=1&rotation=0&showTitle=false&size=50957&status=done&style=none&taskId=u89b235fd-f24f-4eb5-bf3a-e22d55e0d6f&title=&width=643)
这一步可以跳过,直接看第3步
Application.attach方法主要是调用attachBaseContext方法,并且将LoadedApk对象赋值给Application。
![image.png](https://img-blog.csdnimg.cn/img_convert/1c1a0c1f77ce5a77689f0f50ff361189.png#clientId=ub95fd704-f52b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=350&id=u6e7d33d0&margin=[object Object]&name=image.png&originHeight=350&originWidth=716&originalType=binary&ratio=1&rotation=0&showTitle=false&size=46917&status=done&style=none&taskId=ub6adeb55-299b-4673-a6fb-c455caa64a5&title=&width=716)
这个方法就更简单了,直接就调用Application.onCreate,这样Application的创建和launch就结束了
![image.png](https://img-blog.csdnimg.cn/img_convert/7e87e4dc7d59a2d0bf8eed444cfdd53e.png#clientId=ub95fd704-f52b-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=116&id=ud36a9b27&margin=[object Object]&name=image.png&originHeight=116&originWidth=493&originalType=binary&ratio=1&rotation=0&showTitle=false&size=10686&status=done&style=none&taskId=u485a0519-662e-4f3b-b53f-c9c3af724ce&title=&width=493)
找到一张不错的代码流程图,是低于安卓10版本的流程图,和高于android10的流程90%相似,所以拿来主义了。
流程图出处见结尾参考文章
![image.png](https://img-blog.csdnimg.cn/img_convert/ded3c2c9d6029cc6d22aeea21abe6e67.png#clientId=u02e1c685-cb36-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=u2962ac47&margin=[object Object]&name=image.png&originHeight=1238&originWidth=2020&originalType=url&ratio=1&rotation=0&showTitle=false&size=252307&status=done&style=none&taskId=u2fc5498e-3c16-4ad7-9059-b1a60f66d6a&title=)
见参考4
主要是onResume,参见WindowManager中的描述
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。