1 概述
基于Android10源码分析更新
1 | |
相信每位Android开发者对上面的代码都写过无数次了,那么问题来了:
- 根activity(第一个activity)又是如何启动的?
- Application是如何创建的?
- 这个代码是如何启动一个Activity的?
- 内部做了哪些事情?
- onCreate这些生命周期是何时执行的?
- Activity对象何时创建的?
我们不了解内部实现的原理,在平时开发中好像也没有什么问题。其实不然,解决这些问题后,你会对Android系统有更深层次的理解,也会学习到系统源码优秀的设计。并且对解决一些高级问题和深入的性能优化问题有很大帮助,阅读优秀的源码是技术进阶的必要阶段。但另一方面,系统源码是很庞大繁杂的,我们需要带着问题抓住主流程,不能陷入代码细节——这是阅读系统源码以及其他第三方库源码的正确姿势。
2 根Activity启动流程
我们app应用进程是怎么创建的呢?当点击app图标后,Launcher会在桌面activity(此activity就叫Launcher)内调用startActivitySafely方法,startActivitySafely方法会调用startActivity方法,如下图:
此时应用的进程就已经创建出来了。
2.1 入口main()
学过Java的都知道,应用程序入口是public static void main(String[] args)方法,基于Java的Android也一样,Android应用程序的入口在ActivityThread.main()方法中,一切的起源都从main()方法开始:
1 | |
ActivityThread thread = new ActivityThread()创建ActivityThread实例,同时会创建ApplicationThread实例,ApplicationThread是ActivityThread中的一个内部类。然后调用了attach方法:
1 | |
2.2 应用进程和系统服务IPC通信
我们看下ActivityManager.getService()内部执行流程
1 | |
看到IBinder这个标志,这里你应该明白了:这里是获取一个跨进程的服务。
IActivityManager.Stub.asInterface用于将服务端的Binder对象转换成客户端所需的AIDL接口类型的对象,这种转换过程是区分进程的,如果客户端和服务端位于同一进程,那么此方法返回的
就是服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy对象。这里因为是跨进程调用的,返回的是Binder代理对象,这个代理对象实际上代理的是ActivityManagerService,它实现了IActivityManager.Stub接口是Binder本地对象,见android Binder机制。
接着看下mgr.attachApplication(mAppThread, startSeq)方法,前面说过会走到AMS的attachApplication:
1 | |
接着走到attachApplicationLocked()方法很长,这里保留重要的几点:
1 | |
AMS的attachApplicationLocked方法主要三件事:
- 调用IApplicationThread的bindApplication方法,IPC操作,创建绑定Application;
- 通过makeActive方法赋值IApplicationThread
- 通过ATMS启动根activity
先看makeActive方法:
1 | |
mWindowProcessController.setThread(thread)完成了IApplicationThread的赋值。这样就可以依据IApplicationThread是否为空判断进程是否存在了。
再看创建绑定Application的过程:
1 | |
IApplicationThread的bindApplication方法实现是客户端的ApplicationThread的bindApplication方法,它又使用H(之前说过H就是一个Handler),转移到了ActivityThread的handleBindApplication方法(从Binder线程池转移到主线程),看下handleBindApplication方法:
1 | |
主要就是创建Application,并且调用生命周期onCreate方法。创建Application后,内部会attach方法,attach内部会调用attachBaseContext方法,attachBaseContext方法是我们能接触到的一个方法,接着才是onCreate方法。
再来看 根activity 的启动,回到上面AMS的attachApplicationLocked方法,调用了mAtmInternal.attachApplication方法,mAtmInternal是ActivityTaskManagerInternal实例,具体实现是在ActivityTaskManagerService的内部类LocalService,去看看:
1 | |
mRootActivityContainer是RootActivityContainer实例,看下它的attachApplication方法:
1 | |
遍历activity栈,因为我们是第一次启动理论上应该只有一个根activity,然后调用mStackSupervisor.realStartActivityLocked方法
1 | |
中间有段代码如上,通过 ClientTransaction.obtain( proc.getThread(), r.appToken)获取了clientTransaction,其中参数proc.getThread()是IApplicationThread,就是前面提到的ApplicationThread在系统进程的代理。
ClientTransaction是包含一系列的待客户端处理的事务的容器,客户端接收后取出事务并执行。 接着看,使用clientTransaction.addCallback添加了LaunchActivityItem实例:
1 | |
看下LaunchActivityItem实例的获取:
1 | |
new了一个LaunchActivityItem然后设置各种值。我们从名字就能看出,它就是用来启动activity的。它是怎么发挥作用的呢?接着看: 回到realStartActivityLocked方法,接着调用了mService.getLifecycleManager().scheduleTransaction(clientTransaction),mService是ActivityTaskManagerService,getLifecycleManager()方法获取的是ClientLifecycleManager实例,它的scheduleTransaction方法如下:
1 | |
mClient.scheduleTransaction调用IApplicationThread的scheduleTransaction方法。由于IApplicationThread是ApplicationThread在系统进程的代理,所以真正执行的地方就是 客户端的ApplicationThread中了。也就是说,Activity启动的操作又跨进程的还给了客户端。
接着上面的分析,我们找到ApplicationThread的scheduleTransaction方法:
1 | |
2.3 线程切换及消息处理——mH
实际上最后就是调用了mH.sendMessage(msg)方法,之前我们有说过mH实际上是一个Handler,我们看看内部实现:
1 | |
mH是在创建ActivityThread实例时赋值的,是自定义Handler子类H的实例,也就是在ActivityThread的main方法中,并且初始化是已经主线程已经有了mainLooper,所以,使用这个mH来sendMessage就把消息发送到了主线程。
那么是从哪个线程发送的呢?那就要看看ApplicationThread的scheduleTransaction方法是执行在哪个线程了。根据IPC知识,我们知道,服务器的Binder方法运行在Binder的线程池中,也就是说系统进行跨进程调用ApplicationThread的scheduleTransaction就是执行在Binder的线程池中的。但是通过mH一转换,消息最终到了应用的主线程处理了。
那么是怎么处理Activity的启动的呢?接着看。我们找到ActivityThread.H.EXECUTE_TRANSACTION这个消息的处理:取出ClientTransaction实例,调用TransactionExecutor的execute方法,那就看看:
1 | |
跟进executeCallbacks方法:
1 | |
遍历callbacks,调用ClientTransactionItem的execute方法,而我们这里要关注的是ClientTransactionItem的子类LaunchActivityItem,看下它的execute方法:
1 | |
里面调用了client.handleLaunchActivity方法,client是ClientTransactionHandler的实例,是在TransactionExecutor构造方法传入的,TransactionExecutor创建是在ActivityThread中:
1 | |
所以,client.handleLaunchActivity方法就是ActivityThread的handleLaunchActivity方法。
到这里 ApplicationThread把启动Activity的操作,通过mH切到了主线程,走到了ActivityThread的handleLaunchActivity方法。
2.4 Activity初始化及生命周期
接着来看handleLaunchActivity方法:
1 | |
performLaunchActivity主要完成以下事情:
- 从ActivityClientRecord获取待启动的Activity的组件信息
- 通过mInstrumentation.newActivity方法使用类加载器创建activity实例
- 通过LoadedApk的makeApplication方法创建Application对象,内部也是通过mInstrumentation使用类加载器,创建后就调用了instrumentation.callApplicationOnCreate方法,也就是Application的onCreate方法。
- 创建ContextImpl对象并通过activity.attach方法对重要数据初始化,关联了Context的具体实现ContextImpl,attach方法内部还完成了window创建,这样Window接收到外部事件后就能传递给Activity了。
- 通过 mInstrumentation.callActivityOnCreate方法调用Activity的onCreate。
到这里Activity的onCreate方法执行完,那么onStart、onResume呢? 上面看到LaunchActivityItem,是用来启动Activity的,也就是走到Activity的onCreate,那么是不是有 “XXXActivityItem”呢? 有的:
- LaunchActivityItem 远程App端的onCreate生命周期事务
- ResumeActivityItem 远程App端的onResume生命周期事务
- PauseActivityItem 远程App端的onPause生命周期事务
- StopActivityItem 远程App端的onStop生命周期事务
- DestroyActivityItem 远程App端onDestroy生命周期事务
这些对应的都会走到handlexxxActivity方法,这里我们就不再一一分析了。至此根Activity的启动已经完成了,那么普通activity的启动流程呢?
3 普通activity的启动流程
3.1 Activity启动的发起
从startActivity方法开始,会走到startActivityForResult方法:
1 | |
看到里面调用了mInstrumentation.execStartActivity方法,其中一个参数mMainThread.getApplicationThread(),它的类型是ApplicationThread,之前我们说ApplicationThread是ActivityThread的内部类,继承IApplicationThread.Stub,也是个Binder对象,是用于IPC通讯使用的。而Instrumentation具有跟踪application及activity生命周期的功能,用于android 应用测试框架中代码检测。接着看下mInstrumentation.execStartActivity方法:
1 | |
这里看到Activity的启动又交给了ActivityTaskManager.getService():
1 | |
这儿的代码有没有很熟悉?不错,跟我们之前分析的获取ActivityManagerService服务是一样的,不过这儿获取的是ActivityTaskManagerService(ATMS)。ATMS是用于管理Activity及其容器(任务、堆栈、显示等)的系统服务,运行在系统服务进程(system_server)之中。
值得说明的是,ATMS是在Android10中新增的,分担了之前ActivityManagerService(AMS)的一部分功能(activity task相关)。 在Android10 之前 ,这个地方获取的是服务是AMS。查看Android10的AMS,你会发现startActivity方法内也是调用了ATMS的startActivity方法。所以在理解上,ATMS就隶属于AMS。
接着看,ActivityTaskManager.getService().startActivity有个返回值result,且调用了checkStartActivityResult(result, intent):
1 | |
这是用来检查Activity启动的结果,如果发生致命错误,就会抛出对应的异常。看到第一个case中就抛出了 have you declared this activity in your AndroidManifest.xml?——如果Activity没在Manifest中注册就会有这个错误。
3.2 ATMS
到这里,Activity的启动就跨进程(IPC)的转移到系统进程提供的服务ATMS中了,接着看ATMS的startActivity:
1 | |
跟到startActivityAsUser中,通过getActivityStartController().obtainStarter方法获取ActivityStarter实例 然后调用一系列方法,最后的execute()方法是开始启动activity:
1 | |
这儿分了两种情况,不过 不论startActivityMayWait还是startActivity最终都是走到下面这个startActivity方法:
1 | |
里面有调用了startActivityUnchecked方法,之后调用RootActivityContainer的resumeFocusedStacksTopActivities方法。RootActivityContainer是Android10新增的类,分担了之前ActivityStackSupervisor的部分功能。接着跳转到ActivityStack的resumeTopActivityUncheckedLocked方法:
1 | |
跟进resumeTopActivityInnerLocked方法:
1 | |
先对上一个Activity执行pause操作,再执行当前创建操作,代码最终进入到了ActivityStackSupervisor.startSpecificActivityLocked方法中。这里有个点注意下,启动activity前调用了next.showStartingWindow方法来展示一个window,这就是 冷启动时 出现白屏 的原因了。我们继续看ActivityStackSupervisor.startSpecificActivityLocked方法:
1 | |
有个判断条件if (wpc != null && wpc.hasThread()),意思是是否启动了应用进程,内部是通过IApplicationThread是否为空来判断,之前我们讲根activity启动时有说到在WindowProcessController.makeActive方法内部给IApplicationThread赋值,就是用于这儿的判断。这里我们看已启动应用进程的情况,即调用了realStartActivityLocked方法,看到这个realStartActivityLocked方法是不是很熟悉?没错,就是我们前面讲根activity启动流程时调用的mStackSupervisor.realStartActivityLocked方法,之后的流程就跟前面分析的一样了点击查看。
4 总结
完整关系如下:
