深入理解android 启动模式--singleTask
Android启动模式分为Standard,SingleInstance,SingleTop,SingleTask,四种模式,基本上每次面试都是必面。
今天打算自己从Activity 生命周期变化,和onNewIntent ,taskAffinity,是否可以替代singleTask这些角度来重新理解下
SingleTask
依次启动A---B----C三个界面 ,然后从C 跳回B,其中B界面设置为SingleTask
Log 日志如下:
04-25 11:15:41.880 4197-4197/wdwd.com.androidpractice E/AActivity: onCreate
04-25 11:15:41.881 4197-4197/wdwd.com.androidpractice E/AActivity: onResume
04-25 11:16:14.394 4197-4197/wdwd.com.androidpractice E/BActivity: onCreate
04-25 11:16:14.395 4197-4197/wdwd.com.androidpractice E/BActivity: onResume
04-25 11:16:34.578 4197-4197/wdwd.com.androidpractice E/CActivity: onCreate
04-25 11:16:34.578 4197-4197/wdwd.com.androidpractice E/CActivity: onResume
04-25 11:16:55.497 4197-4197/wdwd.com.androidpractice E/BActivity: onNewIntent
04-25 11:16:55.497 4197-4197/wdwd.com.androidpractice E/BActivity: onResume
04-25 11:16:55.805 4197-4197/wdwd.com.androidpractice E/CActivity: onDestroy
可以发现B在第一次启动时正常,当从C重新启动时,这个时候B已经存在,C会被Destroy,然后依次调用B页面的onNewIntent(),onStart(),onResume,这时,B的onCreate方法没有调用,我们可以判断B没有重新生成,而B之上的C被干掉了
这个onNewIntent是干嘛的呢,测试从C跳转到B时传递参数会怎样呢,修改了下代码,A---B 传入参数 2, C----B 时传入参数1
04-25 11:32:40.823 5567-5567/wdwd.com.androidpractice E/BActivity: onCreate
04-25 11:32:40.824 5567-5567/wdwd.com.androidpractice E/BActivity: onResume2
04-25 11:33:08.186 5567-5567/wdwd.com.androidpractice E/BActivity: onNewIntent1
04-25 11:33:08.186 5567-5567/wdwd.com.androidpractice E/BActivity: onResume2
04-25 11:33:08.488 5567-5567/wdwd.com.androidpractice E/CActivity: onDestroy
可以发现 onNewIntent 是在界面没有重新创建时调用的,从A跳过来的Intent依然保存着,onNewIntent 从字面意思来理解重新创建了一个Intent 来接收新的意图,可以在onNewIntent方法中重新设置Intent
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
Log.e("BActivity","onNewIntent"+intent.getStringExtra("cyy"));
}
使用场景分析
singleTask 不能用代码生成,暂时发现只能在清单文件中定义,有人说和FLAG_ACTIVITY_NEW_TASK 有相似之处,还没有尝试,使用了singleTask 后,主要的特点会将该activity 之上的activity 清空,可以用来消除交互界面的嵌套循环
taskAffinity
为什么taskAffinity与singleTask一起介绍,因为与其他模式一起使用时taskAffinity改变,并不会改变taskid,而singleInstance即使不改变taskAffinity 也会改变takid
另外taskAffinity 可以与 android:allowTaskReparenting="true"一起用
allowTaskReparenting用来标记Activity能否从启动的Task移动到taskAffinity指定的Task,默认是继承至application中的allowTaskReparenting=false,如果为true,则表示可以更换;false表示不可以
taskAffinity默认是包名,现在将BActivity 设置为其他taskAffinity
<activity android:name=".lancumode.BActivity"
android:launchMode="singleTask"
android:taskAffinity="wdwd.cyy">
继续依次从A---B---C 启动会发生什么呢
04-25 14:35:48.994 20912-20912/wdwd.com.androidpractice E/AActivity: onCreate
04-25 14:35:48.994 20912-20912/wdwd.com.androidpractice E/AActivity: onResume2283+++true
04-25 14:36:32.937 20912-20912/wdwd.com.androidpractice E/BActivity: onCreate
04-25 14:36:32.938 20912-20912/wdwd.com.androidpractice E/BActivity: onResume2
04-25 14:36:32.938 20912-20912/wdwd.com.androidpractice E/BActivity: onResume2284+++true
04-25 14:37:13.159 20912-20912/wdwd.com.androidpractice E/CActivity: onCreate
04-25 14:37:13.159 20912-20912/wdwd.com.androidpractice E/CActivity: onCreate2284+++false
04-25 14:37:13.160 20912-20912/wdwd.com.androidpractice E/CActivity: onResume
从C----B
04-25 14:37:34.481 20912-20912/wdwd.com.androidpractice E/BActivity: onNewIntent1
04-25 14:37:34.481 20912-20912/wdwd.com.androidpractice E/BActivity: onResume2
04-25 14:37:34.481 20912-20912/wdwd.com.androidpractice E/BActivity: onResume2284+++true
04-25 14:37:34.787 20912-20912/wdwd.com.androidpractice E/CActivity: onDestroy
好像和前面没什么变化,2283 2284是当前页面所属的task,true和false是是否该task的根节点,我们发现C并没有更改taskAffinity 但是它的taskid 还是发生了改变
这时按下HOME键,再点击应用图标,我们发现这时启动的居然是AActivity
一定要使用singleTask吗
我们发现singleTask 是写死在xml当中,是否太重,那么有什么可以替代的呢?
目前发现如果不修改taskAffinity 也就是第二节的效果,完全可以FLAG_ACTIVITY_CLEAR_TOP + Intent.FLAG_ACTIVITY_SINGLE_TOP来代替singleTask 。
另外还有一个标识Intent.FLAG_ACTIVITY_REORDER_TO_FRONT不会销毁该Activity 之上的activity,只将要启动的Activity 放到栈顶,
Intent.FLAG_ACTIVITY_SINGLE_TOP的意思是如果该activity在栈顶则不会重新创建,只会调用onNewIntent---onStart()---onResume