大牛教你详解 Activity 的生命周期,kotlin 反编译工具
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zalppbw7-1608543741156)(//upload-images.jianshu.io/upload_images/16595031-c0cc086386acb172.png?imageMogr2/auto-orient/strip|imageView2/2/w/732/format/webp)]
本身在知乎上问这么基础的问题再加上说我们国内的开发水平比别人的低,也难怪被所有人喷了。。。
接着,回到正题,关于 Activity 生命周期,对于网上也有大量博客讲到这个问题,接下来就给大家讲讲 Activity 的知识:
[](
)1.Activity 生命周期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z0Vq74RB-1608543741159)(//upload-images.jianshu.io/upload_images/16595031-2944a47b0c9ea753.png?imageMogr2/auto-orient/strip|imageView2/2/w/691/format/webp)]
这幅图比较清晰,就不细说,下面我就说说图上没有的吧
[](
)(一)Activity 与进程的关系
作为应用开发者,接触更多的是 Activity/Service/Broadcast/ContentProvider 这四大组件以及线程,往往对于进程没有很多的概念,这是 google 有意为之,除非在 AndroidManifest.xml 文件中配置 android:process 属性,否则一般情况下一个 App 是运行在一个进程中。
在 Android 系统启动的过程中,便创建好 Android 上层应用的环境,即 Android Runtime,一切的应用都是运行在 Android Runtime 这个层面之上。而进程对于 App 来说是完全透明的,在 Activity 进入生命周期之前,会先创建好进程,可以把进程理解为 Activity 的载体。一个进程中可以有多个 Activity,而一个 Activity 必须且只能存在一个进程里;进程里可以不存在任何 Activity,而 Activity 不能离开进程而孤立存在。
[](
)(二)home 键、back 键、电源键、进程管理器
一般情况下
按下 home 键:前台 Activity 依次回调 onPause, onStop;
按下 back 键:前台 Activity 依次回调 onPause, onStop, onDestroy;
按下电源键:前台 Activity 依次 onPause, onStop;
对于进程管理器,采用的 force-stop 的方式,也是直接强杀进程,并且连广播都会隔断。
**为何我要强调是一般情况呢,**目前 android 应用市场比较混乱,各种应用商店,各种 app,里面不乏有很多让手机后台大量消耗 CPU,导致手机卡顿,或者在后台偷偷耗电、跑流量的应用。
**针对这些情况,国内各大手机厂商都会针对 Android 有不同程度的定制与优化。**这可能会导致那些一般情况的理论与实际有所不同。
比如系统有 Low Memory Killer(低内存杀手),在手机内存比较紧张时会强杀应用,这也会导致 Ac
tivity 挂了,这是 Android 自带的机制。对于厂商,比如灭屏杀进程,那么这就可能导致按下电源键,Activity 的生命周期就玩完了;另外,现在大多数 App,拦截返回键功能,使其与 home 键效果一致,那么不排除有对返回键的极端优化情形。
[](
)(三) 横竖屏切换
在未做任何处理的情况,旋转后,Activity 生命周期重新运行:onPause, onStop, onDestroy, onCreate, onStart, onRestoreInstanceState, onResume。
而目前,google 版本的碎片化非常严重,而版本迭代快(今年 5 月份就能看到 Android 7.0),在 Android 不断升级与完善的同时也新增不少功能,这就导致同一个功能也需要变更。
另外,还是前面的说的,对于 configchange 部分厂商会对其行为定制是完全可能的,屏幕的旋转后重走生命周期是比较卡的一个过程。
[](
)(四)launch mode
Activity 启动模式有 4 种:standard、singleTop、singleTask 和 singleInstance。相关文章也很多,这里简单说下我的理解:
standard 是默认方式,一个 Task 中可以有多个相同类型的 Activity;
singleTop(字面理解单例栈顶),是指 task 栈顶只会有一个同类型的 Activity;
singleTask(字面理解单例 task),是指不只是栈顶,整个 task 只会有一个同类型的 Activity;
singleInstance(字面理解单例实例):不只是整个 task 只会有一个同类型 Activity,而且该 task 也只有这一个 Activity;
对于 Activity 实例的单例要求是不断加强: standard < singleTop <singleTask < singleInstance
有了这些简单铺垫,再说下题主的问题**onNewIntent()**的触发时机是在启动 Activity 时却不需要创建新的 Activity 实例的情形下触发。 比如 singleTop 时,当再次启动 task 栈顶的 Activity 会触发;singleTask/singleInstance 时,再次启动 task 的 Activity 会触发。
另外,对于一般 App 尽量少用 singleTask 和 singleInstance 模式,可能会影响用户体验。
[](
)(五) 结束
建议题主,平时多看看 google 官方文档,看 Android 源码,多动手写 demo 程序,另外,就是学会翻墙。
通过打 log 来验证,留给有兴趣的不妨试试,finish()方法在 onCreate,onStart,onResume 等不同地方调用 finish()后,Activity 走的生命周期也是不同的。
[](
)2.基本结构
一个应用程序通常由多个Activity
组成,那么在应用程序中肯定需要一个容器来盛放这些Activity
,必要时通过该容器找到对应的Activity
,并进行相关操作。上一篇文章已经讲过一个应用程序对应一个ActivityThread
,所以自然而然地该容器是ActivityThread
在负责维护,这个容器叫做mActivities
,是一个数组,里面的每一项叫做ActivityRecord
,一个ActivityRecord
对应一个Activity
。
以上仅仅是应用级别的管理容器,但是很多场景下,系统需要找到某一个特定的Activity
,并下发相关数据比如事件分发。所以还必须在系统层面再维护一个容器,这个容器存放在Activity Manager Service
,对应的容器叫做mHistory
,对应的每一项叫做HistroyRecord
。
每个Activity
必须依靠在进程中,每个进程对应一个 AMS 中的ProcessRecord
,通过这个ProcessRecord
可以找到对应的应用的所有Activity
,同时还提供了与Activity
联系的接口IActivityThread
。
所以整个Activity
的管理框架如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-npPLd5Zn-1608543741162)(//upload-images.jianshu.io/upload_images/16595031-e714b473632d5b3b.png?imageMogr2/auto-orient/strip|imageView2/2/w/476/format/webp)]
[](
)3.Activity
启动过程
在 Launch Activity 时,AMS 将对应的 HistoryRecord 作为 token 传递到客服端和客服端的 Activity 建立联系。在 AMS 中 Activity 状态变化时,将通过该联系找到客服端的 Activity,从而将消息或者动作传递应用程序面对的接口:xxxActivity。整个Activity
的启动过程大致可以分为以下几个步骤:
发起
startActivity(intent)
请求AMS 接收到请求后,创建一个
HistroyRecord
对象,并将该对象放到mHistory
数组中调用
app.thread.scheduleLaunchActivity()
AMS 创建
ActivityRecord
对象,将创建的Activity
放入到ActivityRecord
,再将其放入到mActivities
发起
Activity
的onCreate()
方法
对应的步骤如下图所示:
评论