Activity的启动模式
1. 启动模式的类别
- 标准模式(standard)
- 栈顶复用模式(singleTop)
- 栈内复用模式(singleTask)
- 单例模式(singleInstance)
2. 任务栈
任务栈Task,是一种用来放置Activity实例的容器,他是以栈的形式进行盛放,也就是所谓的先进后出,主要有2个基本操作:压栈和出栈,其所存放的Activity是不支持重新排序的,只能根据压栈和出栈操作更改Activity的顺序。启动一个Application的时候,系统会为它默认创建一个对应的Task,用来放置根Activity。默认启动Activity会放在同一个Task中,新启动的Activity会被压入启动它的那个Activity的栈中,并且显示它。当用户按下回退键时,这个Activity就会被弹出栈,按下Home键回到桌面,再启动另一个应用,这时候之前那个Task就被移到后台,成为后台任务栈,而刚启动的那个Task就被调到前台,成为前台任务栈,手机页面显示的就是前台任务栈中的栈顶元素。
3. 四种启动模式的解释
standard
标准模式:在清单文件中声明 Activity 时,如果不设置Activity的启动模式,系统会 默认 将其设置为standard
。每次启动一个标准模式的Activity都会重新创建一个新的实例,不管这个Activity之前是否已经存在实例,一个任务栈中可以有多个实例,每个实例也可以属于不同的任务栈,谁启动了这个Activity,那么这个Activity实例就运行在启动它的那个Activity所在的栈中 。根据上面所说,我们就了解了当用ApplicationContext启动或者在Service中直接调用startActivity启动标准模式Activity时报如下错误的原因了。
android.util.AndroidRuntimeException: Calling startActivity from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
上面错误的原因就是被启动的Activity是标准模式,而发起启动请求的Context不是Activity的Context,未存在Activity栈,而每个Activity实例启动销毁都需要进栈出栈,用栈来存储Activity的信息,所以非Activity Context需要设置FLAG_ACTIVITY_NEW_TASK
属性,启动一个新的Activity栈。
singleTop
栈顶复用模式:在这种模式下,如果新启动的Activity已经位于任务战的栈顶,那么此Activity不会被重新创建,只会重新调用 onNewIntent 方法,这个Activity的onCreate、onStart都不会被系统调用。如果新Activity实例已经存在但不在栈顶,那么重新创建 Activity 并放入栈顶。
singleTask
栈内复用模式:这是一种单实例模式,一个栈中同一个Activity只存在唯一一个实例,无论是否在栈顶,只要存在实例,都不会重新创建,和 singleTop 一样会重新调用 onNewIntent 方法。需要注意的是:如果一个Activity被设置为singleTask模式,那么当栈内已经存在该Activity实例时,再启动该Activity,会让该Activity实例之上的Activity被出栈。举个例子:有四个Activity 分别是 A、B、C和D,A是singleTask模式,当先执行A->B->C->D时,A在栈内已存在实例,此时再调用D->A启动A时,会让A实例之上的B、C、D都出栈。一般项目的MainActivity都设置为此模式,方便放回首页和清空中间Activity。
singleInstance
单实例模式:这是一种加强的singleTask模式,它除了具有singleTask模式的所有特性外,还加强了一点,那就是此种模式的Activity只能单独地位于一个任务栈中,不同的应用去打开这个activity 共享公用的同一个activity。他会运行在自己单独,独立的任务栈里面,并且任务栈里面只有他一个实例存在。应用场景:呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。
4. 启动模式的设置
启动模式有2种设置方式:在AndroidMainifest
设置、通过Intent
设置标志位
4.1 在AndroidMainifest设置
在AndroidMainifest
的Activity
配置进行设置
<activity
android:name="com.demo.Main4Activity"
//通过android:launchMode属性设置
android:launchMode="singleTask"/>
4.2 通过Intent
设置标志位
Intent inten = new Intent (ActivityA.this,ActivityB.class);
//通过Intent的Flag设置
intent,addFlags(Intent,FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
标记为属性
标记位属性 | 含义 |
---|---|
FLAG_ACTIVITY_SINGLE_TOP | 指定启动模式为栈顶复用模式(SingleTop ) |
FLAG_ACTIVITY_NEW_TASK | 指定启动模式为栈内复用模式(SingleTask ) |
FLAG_ACTIVITY_CLEAR_TOP | 所有位于其上层的Activity都要移除,SingleTask 模式默认具有此标记效果 |
网友评论