android源码宇宙-activity启动源码

源码

关键类说明

1、ActivityRecord

Activity栈中的一个节点,用于展示一个Activity
它集成了WindowToken实现了WindowManagerService中的一个接口
image.png
既然如此顺便看看WindowToken吧
image.png

ActivityTaskSupervisor

用来替代ActivityStackSupervisor
image.png

Instrumentation

这东西是ActivityThread中的一个变量
它可以作为一个测试框架的根基,因为它是先于我们的Application和Activity启动的,所以它可以监听到我们创建Activity和Application操作。
android是支持自定义Instrumentation的,可以通过继承Instrumentation重写里面的方法实现监听

顺手找了一篇参考文章:https://blog.csdn.net/weixin_42355665/article/details/117661233

启动过程源码

  1. startActivity方法

image.png

  1. startActivityForResult方法

最终会走到Instrumentation.execStartActivity方法
image.png

  1. Instrumentation.execStartActivity方法

ActivityTaskManager.getService()返回结果就是IActivityTaskManager类型
需要说明的是本方法中最后一步调用的checkStartActivityResult方法可以根据返回的result判断启动activity的结果

checkStartActivityResult方法的实现可以查看 附1中内容

image.png
这里的ActivityTaskManager.getService()要说明一下,它最终调用到了ActivityTaskManager中的单例,然后获取binder调用接口
image.png
所以这里的ActivityTaskManager.getService().startActivity实际上就是ActivityTaskManagerService.startActivity

  1. ActivityTaskManagerService.startActivity

image.png

  1. startActivityAsUser

image.png

  1. ActivityStarter.execute

这里负责执行启动逻辑
image.png
image.pngimage.png

  1. executeRequest

代码巨长,关键代码在结尾处startActivityUnchecked
image.png

  1. startActivityUnchecked
  2. startActivityInner
  3. Task.startActivityLocked
  4. Task.resumeTopActivityUncheckedLocked
  5. ActivityTaskSupervisor.startSpecificActivity
  6. ActivityTaskSupervisor.realStartActivityLocked
  7. ClientTransaction.addCallback
  8. ClientLifecycleManager.scheduleTransaction

mService.getLifecycleManager().scheduleTransaction(clientTransaction)

  1. ClientTransaction.schedule
  2. IApplicationThread.scheduleTransaction

实际类型是ApplicationThread.scheduleTransaction
image.png

  1. ApplicationThread.H.sendMessage()
  2. TransactionExecutor.execute

mTransactionExecutor.execute(transaction);

  1. ActivityThread.handleLaunchActivity

image.png

  1. ActivityThread.performLaunchActivity

createBaseContextForActivity方法的说明见:附2

下图中的newActivity用来创建Activity对象,实际上如果我们的Application如果没有创建,它会连带Application一起创建。但是似乎这个Application的创建并没有意义,只是个站位作用。

image.png
下图中appContext.setOuterContext(activity);方法,将我们的的activity对象赋值给ContextImpl,目的是让他们产生关联。

在Activity.attach方法中,只做了一件事,就是调用onAttachFragment方法来初始化Fragment

makeApplication方法的说明见附3

image.png
image.png

  1. ActivityThread.callActivityOnCreate方法

这个方法过后逻辑终于又转到了Activity中
image.png

  1. 最终方法会调用到performCreate方法

image.png

本节参考: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通信,

  1. 用于进程调用ActivityTaskManagerService.startActivity,代码进入atms进程中执行
  2. ClientTransaction类中IApplicationThread.scheduleTransaction,atms调用应用进程的Binder让Activity启动逻辑回到应用进程

1、Instrumentation.checkStartActivityResult方法

@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);
    }
    }

2、ActivityThread.createBaseContextForActivity是如何创建上下文的

![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)

3、ActivityThread.performLaunchActivity方法中的makeApplication是如何工作的

  1. makeApplication方法

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)

  1. Instrumentation.newApplication创建Application对象

这一步可以跳过,直接看第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)

  1. Instrumentation.callApplicationOnCreate方法

这个方法就更简单了,直接就调用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)

4、流程图

找到一张不错的代码流程图,是低于安卓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=)

Intent传输数据不能超过1mb原因分析

  1. 由于Activity通过intent传值,是通过App进程将intent携带的数据传输到AMS进程,最终通过Binder事务缓冲区完成数据传输
  2. 目前Binder事务缓冲区的大小固定有限,目前为1MB,进程中正在处理的所有事务共享
  3. 由于此限制是进程级别而不是Activity级别的限制,因此这些事务包括应用中的所有 binder 事务,超过大小限制时,将引发TransactionTooLargeException。

见参考4

5、onCreate后的生命周期

主要是onResume,参见WindowManager中的描述

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论

打赏作者

卡布哥哥学安卓

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值