Android四大组件之Activity
总结下自己对Activity的理解,首先个人觉得要想弄白一件事,那么就因该从源头开始,好了,废话不多说了,先从Activity框架说起吧
Activity框架和管理结构
Activity管理的核心是AcitivityManagerService,是一个独立的进程
ActiveThread是每一个应用程序所在进程的主线程,循环的消息处理
ActiveThread与AcitivityManagerService的通信是属于进程间通信,使用binder机制
binder机制,我会在后面的“Android插件化机制”上来详细说明
Activity启动过程
以启动一个应用程序startActivity为例看一下代码执行的大概流程:
可将其分为6个过程:
使用代理模式启动到ActivityManagerService中执行
创建ActivityRecord到mHistory记录中
通过socket通信到Zgote相关类创建process
通过ApplicatonThread与ActivityManagerService建立通信
ActivityManagerService通知ActiveThread启动Activity的创建
ActivityThread创建Activity加入到mActivities中并开始调度Activity执行
请看下图:
并不是所有启动一个Activity都是这样的过程:一个应用程序中所有Activity只有一个ActivityThread属于一个Process,ActivityStack并不是每次都需要创建一个Stack来管理Activities。
下面看看adnroid系统中四个重要概念:
Application:由多个相关的松散的与用户进行交互Activity组成,通常被打包成apk后缀文件中
Activities:应用程序的主要组成部分,是应用程序的核心
ActivityStack:将应用程序中打开的Activity保存在历史栈中,按照栈的先进后出的原则,Start Activity时入栈,返回时出栈
Task:将一系列相关的Activity组合,完成某个应用程序完整操作,不管activity属于哪个Application的
例如:写信息—调用—文件管理,都属于一个Task,但属于两个Application
Activity启动流程类结构分析
ActivityService相关类
使用了Proxy代理模式:ActivityManagerProxy代理ActivityManagerService,并为之提供了公共的访问接口:IActivityManager
Activity启动
ActivityStack管理
ActivityStack创建并存储系列创建的Activity实例,将其入栈管理mHistory
ActivityThread
这种管理在应用进程的主线程的执行,在活动管理器请求时调度和执行活动,广播和其他操作,是应用程序的主线程,消息循环执行者;其中有很多的内部类来完成工作。
ActivityThread使用内部类:ApplicationThread与ActivityManagerService进行通信,
ActivityThread将状态变化传递控制客户端Activity的状态执行;
mActivities保存由ActivityStack所创建的ActivityRecord相关实例引用;
到这里是对Activity工作机制,以下开始对Activity生命周期解刨。
Activity生命周期
如图可以看出,Activity生命周期的走势,从onCreate开始到onDestory在不同场景下的走势情况
图中需要注意一下几点:
Activity实例是由系统自动创建,并在不同的状态期间回调相应的方法。一个最简单的完整的Activity生命周期会按照如下顺序回调:onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy。称之为entire lifetime。
当执行onStart回调方法时,Activity开始被用户所见(也就是说,onCreate时用户是看不到此Activity的,那用户看到的是哪个?当然是此Activity之前的那个Activity),一直到onStop之前,此阶段Activity都是被用户可见,称之为visible lifetime。
当执行到onResume回调方法时,Activity可以响应用户交互,一直到onPause方法之前,此阶段Activity称之为foreground lifetime。
A-Activity to B-Activity之间的交互
如下图:
从这第三幅图中可知道,其他两图是一个正常Activity的流程
A to B 将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop。
B to A 将依次执行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy。
到这里相信大家对Activity的生命周期有所了解,不懂的请动手打印下日志即可看出,Activity生命周期不难理解,而且也很直观,下面加入Activity启动模式来让你的Activity显得更加得心应手。
Activity启动模式
Activity的启动模式分为四种
standard
标准 - 默认模式,在不指定启动模式的前提下,系统默认使用该模式启动活动,每次启动一个活动都会重写创建一个新的实例,不管这个实例存不存在。这种模式下,谁启动了该模式的活动,该活动就属于启动它的活动的任务栈中这个活动它的的onCreate(),在onStart(),的onResume()方法都会被调用。
配置形式: <activity android:name=".MainActivity" android:launchMode="standard" />
singleTop
栈顶复用模式,如果新的这个活动已经位于栈顶,那么活动不会被重写创建,同时它的onNewIntent方法会被调用,通过此方法的参数我们可以去除当前请求的信息。如果栈顶不存在该活动的实例,则情况与标准模式相同需要注意的是这个活动它的的onCreate(),在onStart()方法不会被调用,因为它并没有发生改变。
配置形式:<activity android:name=".MainActivity" android:launchMode="singleTop" />
singleTop模式分3种情况
1、当前栈中已有该活动的实例并且该实例位于栈顶时,不会新建实例,而是复用栈顶的实例,并且会将意图对象传入,回调onNewIntent方法
2、当前栈中已有该活动的实例但是该实例不在栈顶时,其行为和标准启动模式一样,依然会创建一个新的实例
3、 当前栈中不存在该活动的实例时,其行为同标准启动模式
标准和singleTop启动模式都是在原任务栈中新建活动实例,不会启动新的任务,即使你指定了taskAffinity属性。
那么什么是taskAffinity属性呢,可以简单的理解为任务相关性。
这个参数标识了一个活动所需任务栈的名字,默认情况下,所有活动所需的任务栈的名字为应用的包名
我们可以单独指定每一个活动的taskAffinity属性覆盖默认值
一个任务的亲和力决定于这个任务的根活动(根活动)的taskAffinity
在概念上,具有相同的亲和力的活性(即设置了相同taskAffinity属性的活动)属于同一个任务
为一个活动的taskAffinity设置一个空字符串,表明这个活动不属于任何任务。
很重要的一点taskAffinity属性不对标准和singleTop模式有任何影响,即时你指定了该属性为其他不同的值,这两种启动模式下不会创建新的任务(如果不指定即默认值,即包名)
指定方式如下:<activity android:name=".ActivitySingleTop" android:launchMode="singleTop" android:taskAffinity="packageName"/>
singleTask
栈内复用模式,这个模式十分复杂,有各式各样的组合。在这个模式下,如果栈中存在这个活动的实例就会复用这个活动,不管它是否位于栈顶,复用时,会将它上面的活性全部出栈,并且会回调该实例的onNewIntent方法。其实这个过程还存在一个任务栈的匹配,因为这个模式启动时,会在自己需要的任务栈中寻找实例,这个任务栈就是通过taskAffinity属性指定。如果这个任务栈不存在,则会创建这个任务栈。
配置形式:<activity android:name=".SingleTaskActivity" android:launchMode="singleTask" >
singleTask启动模式启动活动时,首先会根据taskAffinity去寻找当前是否存在一个对应名字的任务栈
如果不存在,则会创建一个新的任务,并创建新的活动实例入栈到新创建的任务中去
如果存在,则得到该任务栈,查找该任务栈中是否存在该活动实例
如果存在实例,则将它上面的活动实例都出栈,然后回调启动的活动实例的onNewIntent方法
如果不存在该实例,则新建活动,入栈并
此外,我们可以将两个不同应用程序中的活动设置为相同的taskAffinity,这样虽然在不同的应用中,但是活动会被分配到同一个任务中去。如果指定了相同的taskAffinity的Activity被启动到了同一个任务中
singleInstance
全局唯一模式, 该模式具备singleTask模式的所有特性外,与它的区别就是,这种模式下的活动会单独占用一个任务栈,具有全局唯一性,即整个系统中就这么一个实例,由于栈内复用的特性,后续的请求均不会创建新的活动实例,除非这个特殊的任务栈被销毁了。以singleInstance模式启动的活动在整个系统中是单例的,如果在启动这样的Activiyt时,已经存在了一个实例,那么会把它所在的任务调度到前台,重用这个实例。
配置形式:<activity android:name=".singleinstance.SingleInstanceActivity" android:launchMode="singleInstance" >
如果系统中不存在该实例,所以新建了一个Task,按home键后,使用另一个App进入该Activity,由于系统中已经存在了一个实例,不会再创建新的Task,直接复用该实例,并且回调onNewIntent方法。可以从他们的hashcode中可以看出这是同一个实例。因此我们可以理解为:SingleInstance模式启动的Activity在系统中具有全局唯一性。
综上所述,纯属个人愚见,也建议读者动手实践,动手才是王道,欢迎大家一起探讨![这里写图片描述]