Activity的启动模式和启动流程

简介: 标准模式(standard)栈顶复用模式(singleTop)栈内复用模式(singleTask)单例模式(singleInstance)启动模式可在AndroidManifest.xml中,通过<activity>标签的android:launchMode属性设置。

1.Android四种Activity启动方式:


标准模式(standard)

栈顶复用模式(singleTop)

栈内复用模式(singleTask)

单例模式(singleInstance)


启动模式可在AndroidManifest.xml中,通过<activity>标签的android:launchMode属性设置。


2.启动模式的结构——栈(后进先出)


任务栈(Task Stack)或者叫退回栈(Back Stack)介绍:


1.任务栈用来存放用户开启的Activity。


2.在应用程序创建之初,系统会默认分配给其一个任务栈(默认一个),并存储根Activity。


3.同一个Task Stack,只要不在栈顶,就是onStop状态:


4.任务栈的id自增长型,是Integer类型。


e875d4ec332f4fa2598f3f6ce0dc92b.png


5.新创建Activity会被压入栈顶。点击back会将栈顶Activity弹出,并产生新的栈顶元素作为显示界面(onResume状态)。


6.当Task最后一个Activity被销毁时,对应的应用程序被关闭,清除Task栈,但是还会保留应用程序进程(狂点Back退出到Home界面后点击Menu会发现还有这个App的框框。个人理解应该是这个意思),再次点击进入应用会创建新的Task栈。


3.启动方式详解


3.1标准模式



       特点:1.Activity的默认启动模式

                  2.每启动一个Activity就会在栈顶创建一个新的实例。


应用场景: 绝大多数Activity,mainfest中没有配置就默认标准模式。如果以这种方式启动的Activity被跨进程调用,在5.0之前新启动的Activity实例会放入发送Intent的Task的栈的顶部,尽管它们属于不同的程序,这似乎有点费解看起来也不是那么合理,所以在5.0之后,上述情景会创建一个新的Task,新启动的Activity就会放入刚创建的Task中,这样就合理的多了。


 缺点:当Activity已经位于栈顶时,而再次启动Activity时还需要在创建一个新的实例,不能直接复用。


3.2 singleTop模式(栈顶复用)



    如果需要新建的Activity位于任务栈栈顶,那么此Activity的实例就不会重建,而是重用栈顶的实例。并回调如下方法: 由于不会重建一个Activity实例,则不会回调其他生命周期方法。


@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
}

实例

打开步骤:MainActivity->SingleTaskActivity->SingleTaskActivity->OtherActivity->SingleTaskActivity->SingleTaskActivity

第一次启动SingleTopActivity的时候会执行onCreate()方法新建一个实例,然后再次启动SingleTopActivity页面会回调onNewIntent(),说明没有创建新的实例,而且hashCode值没有发生改变。此时我们继续打开另一个Activity,这时OtherActivity处于栈顶,我们继续启动SingleTopActivity,这时发现又是执行了onCreate(),说明又重新创建了新的实例,当我们继续启动SingleTopActivity,发现回调了onNewIntent(),同样hashCode值没有发生改变,证明没有重新创建实例。


应用场景:


在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。

当然实际的开发过程中,测试妹纸没准给你提过这样的bug:某个场景下连续快速点击,启动了两个Activity。如果这个时候待启动的Activity使用 singleTop模式也是可以避免这个Bug的。同standard模式,如果是外部程序启动singleTop的Activity,在Android 5.0之前新创建的Activity会位于调用者的Task中,5.0及以后会放入新的Task中。

3.3singleTask模式(栈内复用)



特点:

该模式是一种单例模式,即一个栈内只有一个该Activity实例。每次启动Activity时系统首先检查栈中是否存在当前Activity实例。如果存在则直接复用,并把当前Activity之上所有实例全部出栈。


其次,第一次启动SingleTaskActivity的时候会执行onCreate()方法新建一个实例,然后再次启动SingleTaskActivity页面会回调onNewIntent(),说明没有创建新的实例,而且hashCode值没有发生改变。此时我们继续打开另一个Activity,然后继续启动SingleTaskActivity,这时发现仍然只回调onNewIntent(),说明没有创建新的实例,当我们继续启动SingleTaskActivity,仍然只是回调了onNewIntent(),此过程中发现hashCode值始终没有发生改变,证明引用都是同一个的实例。


应用场景:

大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。在跨应用Intent传递时,如果系统中不存在singleTask Activity的实例,那么将创建一个新的Task,然后创建SingleTask Activity的实例,将其放入新的Task中。


应用案例

例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。


3.4singleInstance模式(单例模式)



特点:

该模式的Activity会启动一个新的任务栈来管理Activity实例,并且该实例在整个系统中只有一个。无论从那个任务栈中启动该Activity,都会是该Activity所在的任务栈转移到前台,从而使Activity显示。主要作用是为了在不同程序中共享一个Activity。通过测试发现,在第一次打开SingleInstanceActivity的时候,由于系统不存在该实例,所以系统会新建一个任务栈来存放该Activity实例,而且只要打开过一次该Activity,后面无论什么时候再次启动该Activity,都会直接引用第一次创建的实例,而且会回调该实例的onNewIntent()方法。


应用场景:

系统Launcher、锁屏键、来电显示等系统应用。


70a80e0dc8a14e7a8aded5063c94af8.png




4.Activity启动流程


(涉及源码,我就不多赘述了,大致流程走一下)


Activity的启动流程一般是通过调用startActivity或者是startActivityForResult来开始的

startActivity内部也是通过调用startActivityForResult来启动Activity,只不过传递的requestCode小于0

Activity的启动流程涉及到多个进程之间的通讯这里主要是ActivityThread与ActivityManagerService之间的通讯

ActivityThread向ActivityManagerService传递进程间消息通过ActivityManagerNative,ActivityManagerService向ActivityThread进程间传递消息通过IApplicationThread。

ActivityManagerService接收到应用进程创建Activity的请求之后会执行初始化操作,解析启动模式,保存请求信息等一系列操作。

ActivityManagerService保存完请求信息之后会将当前系统栈顶的Activity执行onPause操作,并且IApplication进程间通讯告诉应用程序继承执行当前栈顶的Activity的onPause方法;

ActivityThread接收到SystemServer的消息之后会统一交个自身定义的Handler对象处理分发;

ActivityThread执行完栈顶的Activity的onPause方法之后会通过ActivityManagerNative执行进程间通讯告诉ActivityManagerService,栈顶Actiity已经执行完成onPause方法,继续执行后续操作;

ActivityManagerService会继续执行启动Activity的逻辑,这时候会判断需要启动的Activity所属的应用进程是否已经启动,若没有启动则首先会启动这个Activity的应用程序进程;

ActivityManagerService会通过socket与Zygote继承通讯,并告知Zygote进程fork出一个新的应用程序进程,然后执行ActivityThread的mani方法;

在ActivityThead.main方法中执行初始化操作,初始化主线程异步消息,然后通知ActivityManagerService执行进程初始化操作;

ActivityManagerService会在执行初始化操作的同时检测当前进程是否有需要创建的Activity对象,若有的话,则执行创建操作;

ActivityManagerService将执行创建Activity的通知告知ActivityThread,然后通过反射机制创建出Activity对象,并执行Activity的onCreate方法,onStart方法,onResume方法;

ActivityThread执行完成onResume方法之后告知ActivityManagerService onResume执行完成,开始执行栈顶Activity的onStop方法;

ActivityManagerService开始执行栈顶的onStop方法并告知ActivityThread;

ActivityThread执行真正的onStop方法;


相关文章
|
Shell Android开发 容器
你真了解Android任务栈 Task 与启动模式吗?
你真了解Android任务栈 Task 与启动模式吗?
132 0
|
存储 Android开发
温故知新—Activity的五种启动模式
Activity的五种启动模式
212 0
温故知新—Activity的五种启动模式
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(二)
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(二)
217 0
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(二)
|
Linux Android开发
【Android 启动过程】Android 应用启动流程 | Activity 启动流程
【Android 启动过程】Android 应用启动流程 | Activity 启动流程
415 0
【Android 启动过程】Android 应用启动流程 | Activity 启动流程
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( Activity -> AMS、主线程阶段 )
【Android 启动过程】Activity 启动源码分析 ( Activity -> AMS、主线程阶段 )
212 0
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 一 )
【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 一 )
488 0
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )
【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )
232 0
|
Java Android开发
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(一)
【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )(一)
229 0
|
Android开发 数据格式 XML
Activity的启动模式
任务栈 android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。 我们每次打开一个新的Activity或者退出当前Activity都会在一个称为任务栈的结构中添加或者减少一个Activity组件,因此一个任务栈包含了一个activity的集合, android系统可以通过Task有序地管理每个activity,并决定哪个Activity与用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。
1108 0