美文网首页组件android技术杂荟Android架构设计
深入理解android 启动模式--singleTask

深入理解android 启动模式--singleTask

作者: 岁月留痕 | 来源:发表于2017-04-25 16:58 被阅读11117次

    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

    相关文章

      网友评论

      • 373368212db0:楼主麻烦看下我这个场景:
        启动页AActivity设置为singleTask,跳转到BActivity(为普通模式),这个时候推到home页面,再点击icon打开app,先执行了AActivity的onNewIntent,这是为什么呢?AActivity和BActivity都没有设置taskAffinity参数。
      • 男子汉大豆腐:singleTask 模式应该是和 FLAG_ACTIVITY_CLEAR_TOP 表现一样,和
        FLAG_ACTIVITY_NEW_TASK 除了名字,没有什么共同之处,另外,FLAG_ACTIVITY_NEW_TASK 可以配合其他 FLAG,有更复杂的行为,表现要复杂得多。
      • one_cup:楼主你觉得点击Home键之后吗,再重新点击图标启动的是AActivity是为什么?
        one_cup:@岁月留痕 楼主说的对,应该是启动默认包名的task,这个task中只有AActivity,同时猜测,系统当时并不知道另一个task的名字是什么。https://blog.piasy.com/2017/01/16/Android-Basics-Task-and-LaunchMode/
        岁月留痕:这个可能要看下罗升阳的Android应用程序启动过程源代码分析吧
        我理解的是应用主task栈中只有aactivity,点击图标的时候会先启动当前栈顶部的activity,而这时bc已经在另外一个栈中

      本文标题:深入理解android 启动模式--singleTask

      本文链接:https://www.haomeiwen.com/subject/ixfvzttx.html