面试题十七:Activity的启动流程是怎样的?
Activity的启动流程是怎样的?
一、面试官视角:这道题想考察什么?
- 是否熟悉Activity启动过程中与AMS(Activity Manager Service)的交互过程
- 是否熟悉Binder通信机制
- 是否了解插件化框架如何Hook Activity启动
- 阐述Activity转场动画的实现原理
- 阐述Activity的窗口显示流程
二、题目剖析
0、Activity跨进程启动
跨进程启动流程:
在【请求进程A】中调用startActivity,通过AMP启动Activity,AMP指的是AMS在通信过程中在客户端的一个代理,我们通过AMP来调用AMS一些方法来启动Activity,启动Activity的过程当中,会在【system_server进程】中解析Activity信息、处理启动参数、启动目标进程、绑定新进程,而启动目标进程是通过Zygote,直接Fork出来一个进程,在Android里面所有的进程都是通过Zygote Fork出来的,这样的话我们就可以共享到一些预加载的资源等,启动速度也会变得更快。然后通过调用ATP(ATP指的是ApplicationThread在system_server端的一个代理)的scheduleLaunchActivity,本质上是调用的ApplicationThread的方法,进而在【目标进程B】中去启动Activity。
以上就是跨进程启动Activity的流程,比如通过Launcher来启动自己的进程就是这么干的,Launcher在里面调用startActivity,你点桌面icon的时候就会触发这个流程。
1、Activity进程内启动
在【请求进程A】中调用startActivity,通过AMP启动Activity,AMP指的是AMS在通信过程中在客户端的一个代理,我们通过AMP来调用AMS一些方法来启动Activity,启动Activity的过程当中,会在【system_server进程】中解析Activity信息、处理启动参数,然后通过ATP(ATP指的是ApplicationThread在system_server端的一个代理)的scheduleLaunchActivity,本质上是调用的ApplicationThread的方法,进而在【请求进程A】中去启动Activity。
2、与AMS如何交互
通过AMP,AMP指的是AMS在通信过程中在客户端的一个代理,我们通过AMP来调用AMS一些方法来启动Activity。
3、Activity的参数和结果如何传递
启动Activity的时候,有跨进程的调用,那么跨进程的调用是通过Binder来实现通信的,Binder本身有一个缓冲区,但这个缓冲区有大小的限制,如果你启动Activity的时候,携带数据过大的话会有问题的,而且数据必须可以序列化。
数据过大的话,如何传递呢?
如果能确保Activity在同一进程当中,使用Model进行数据共享,首先在Activity A将数据设置到Model中,然后从Activity A传递一个key到Activity B就可以了,然后在Activity B中通过key去Model里面读取数据即可,这样的话,也可以实现数据与页面的解耦。
如果Activity跨进程的话,就需要实现可进程间通信,这个Model可以是一个进程间可以访问的,比如使用ContentProvider来访问。
4、Activity如何实例化
1 |
|
1 |
|
5、Activity、Fragment为什么不能添加有参数的构造方法?
这就涉及到Activity状态保存和恢复,比如从ActivityA到ActivityB,然后又从ActivityB回到ActivityA,之前讲匿名内部类也是这种场景,其实同样的场景下还涉及到一个Activity状态如何保存和恢复的问题!状态的保存和恢复有个重要的点就是FragmentManager,它会在ActivityA被销毁的时候,也就是ActivityA要保存状态的时候,把ActivityA里面持有的Fragment保存到一个叫android:fragments这么一个key的数据里面,等到ActivityA要恢复的时候再把它恢复出来,那Activity和Fragment如何恢复呢?还不就是通过上面所说的类似调用newInstance()方法进行恢复,要想成功调用newInstance()方法,就必须要有一个默认的无参的构造方法,所以这就是为什么不能添加有参数的构造方法的原因所在,就算你写了有参的构造方法,也要提供一个默认的无参的构造方法。
5、Activity生命周期如何流转
ActivityThread - handleLaunchActivity:
newActivity
activity - attach
activity - create
activity - start
activity - restoreState
activity - postCreate
activity - resume
activity - makeVisible
6、Activity的窗口如何展示
ActivityThread - handleLaunchActivity:
newActivity
activity - attach(调用createPhoneWindow,创建窗口)
activity - create
activity - start
activity - restoreState
activity - postCreate
activity - resume
从create()到resume(),才会去触发DecorView的创建(期间包括addContentView、setContentView、getDecorView)
activity - makeVisible
makeVisible()才会显示DecorView,显示的内容包括status bar、action bar、content view;所以在resume()或之前,想获取Activity View的大小的话,你会发现它们返回的始终是0,因为DecorView还没有显示丫!但如果你在resume()使用handler直接调用post,让它放到下一帧去获取view的大小就可以获取到了,因为在resume()之后马上就把DecorView给显示出来了。
7、Activity转场动画的实现机制
1 |
|
三、题目结论
- Activity启动流程是一个庞大的题目,足够灵活
- 启动过程中涉及到AMS的交互与插件化紧密相关
- 参数传递机制的可与架构设计联系进行迁移
- 生命周期与窗口展示可以向事件处理、UI绘制等话题迁移
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!