Android复习-任务栈与Activity启动标记(使用标记启动Activity时的坑)

任务栈,我们说过任务栈的概念,也知道了它的作用,但是在使用过程中会有一些坑。

指定任务栈:

        <activity
            android:name=".Main2Activity"
            android:launchMode="standard"
            android:taskAffinity="com.net.wrf"/>

这个时候就给此Activity指定了它的任务栈,但是它起不起作用还是得具体分析。

比如现在有两个Activity,A和B,App首先进入A,启动模式都为standard,并且为B指定taskAffinity属性,因为不指定的话就默认为应用包名,所以这样指定了就相当于为B创建一个名为com.net.wrf的任务栈,那么事实是这样吗?

启动A:

03-13 16:05:24.036 17192-17192/? I/mydata: Main3Activity...onCreate
03-13 16:05:24.036 17192-17192/? I/mydata: Main3Activity..taskId..1630
03-13 16:05:24.037 17192-17192/? I/mydata: Main3Activity...onStart
03-13 16:05:24.037 17192-17192/? I/mydata: Main3Activity...onResume

A启动B:

03-13 16:05:30.185 17192-17192/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onPause
03-13 16:05:30.231 17192-17192/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onCreate
03-13 16:05:30.231 17192-17192/ryrj.pzfw.net.activitytest I/mydata: Main2Activity..taskId..1630
03-13 16:05:30.231 17192-17192/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onStart
03-13 16:05:30.232 17192-17192/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onResume
03-13 16:05:30.688 17192-17192/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStop

可以发现,B还是进入了A所在的任务栈,那么taskAffinity没起作用。


那么还有一种情况,就是我们不改变上面的配置,A中启动一个Service,在Serivce内启动B:

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        Log.i("mydata","startActivity");
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent intent1 = new Intent(MyIntentService.this,Main2Activity.class);
                intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent1);
            }
        },3000);
        return super.onStartCommand(intent, flags, startId);
    }

我们必须加上标记为Intent.FLAG_ACTIVITY_NEW_TASK,否则无论如何都启动不了。

那么这种方式启动的B会发生什么呢?

03-13 16:08:37.171 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onCreate
03-13 16:08:37.171 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main3Activity..taskId..1633
03-13 16:08:37.172 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStart
03-13 16:08:37.172 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onResume

03-13 16:08:57.788 19176-19176/ryrj.pzfw.net.activitytest I/mydata: startActivity

03-13 16:09:00.856 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onPause
03-13 16:09:00.916 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onCreate
03-13 16:09:00.916 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main2Activity..taskId..1634
03-13 16:09:00.917 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onStart
03-13 16:09:00.917 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onResume
03-13 16:09:01.639 19176-19176/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStop


可以看出,这时任务栈确实不一样了,如果不指定taskAffinity,那么在service中启动的Activity虽然用了标记FLAG_ACTIVITY_NEW_TASK,则无论是standard或者singleTask模式,都会加入到已经存在的那个任务栈中(当然要是非singleInstance任务栈)。


所以总结一下:并不是指定了FLAG_ACTIVITY_NEW_TASK,就要为所启动的activity创建新的任务栈。

并且Android艺术探索与开发上任主席说FLAG_ACTIVITY_NEW_TASK的作用相当于在XML文件中指定singleTask模式,我觉得这个是不对的,你不信在一个service中多次使用这个标记启动一个standard模式的activity,并不会调用onNewIntent,会一直重建实例,和singleTask效果并不一样。有图有证据:

03-13 16:25:55.495 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onCreate
03-13 16:25:55.496 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main3Activity..taskId..1647
03-13 16:25:55.496 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStart
03-13 16:25:55.496 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onResume

03-13 16:26:00.962 30665-30665/ryrj.pzfw.net.activitytest I/mydata: startActivity

03-13 16:26:04.008 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onPause
03-13 16:26:04.064 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onCreate
03-13 16:26:04.065 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity..taskId..1647
03-13 16:26:04.065 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onStart
03-13 16:26:04.066 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onResume
03-13 16:26:04.537 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main3Activity...onStop

03-13 16:26:08.559 30665-30665/ryrj.pzfw.net.activitytest I/mydata: startActivity

03-13 16:26:11.608 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onPause
03-13 16:26:11.651 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onCreate
03-13 16:26:11.651 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity..taskId..1647
03-13 16:26:11.652 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onStart
03-13 16:26:11.652 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onResume
03-13 16:26:12.117 30665-30665/ryrj.pzfw.net.activitytest I/mydata: Main2Activity...onStop

有人说想要想达到singleTask的效果,必须得用两个标记位:

                intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

而Android开发与探索中对FLAG_ACTIVITY_CLEAR_TOP的解释是,清空它以及它之上的实例,确实是如此,但是并不会回调onNewIntent方法(因为前面的那个相同Activity实例已经被销毁了),还是有一点区别的。


在Service中启动一个Activity如何达到singleTop效果:

                intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);

这个确实可以达到singleTop效果,并且onNewIntent方法也会被回调。


如何达到一种singleInstance的效果:

                intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

这个确实会保证一个栈中只有一个实例,但是它却是每次都情况栈,然后创建一个新的实例入栈的,不会复用,也不会调用onNewIntent方法。


所以总结:在Service或BoardCastReceiver中启动Activity时一定要加上FLAG_ACTIVITY_NEW_TASK标记,并且请勿使用诸如CLEAT_TOP或者CLEAT_TASK来达到singleTask或者singleInstance的效果,因为却是表现一样,但实质不一样,还是去XML中指定的为好。


好了,现在来在正常activity中通过标记来启动activity实验:

FLAG_ACTIVITY_NEW_TASK : 

场景A加上标记启动B,不会为B创建新栈,B启动A,然后再次A启动B,也不会出现出栈的情况,栈中实例情况为ABAB,所以我觉得它自己使用时没用。

FLAG_ACTIVITY_CLEAR_TOP:

场景A加上标记启动B,创建B,B启动A,创建A,这时是ABA,A再启动B,则BA出栈,创建一个新的A的入栈。

FLAG_ACTIVITY_CLEAR_TASK:

场景A加上标记启动B,创建B,B启动A,然后A再启动B,没有任何影响。。

FLAG_ACTIVITY_SINGLE_TOP:

场景A加上标记启动B,创建B,B启动A,然后A再启动B,没有任何影响。。


总结一下:这些标记单独使用,只有clearTop是起作用的,其余的不起作用。

然后我就试了一下上面在service中组合使用的情况下,发现使用Service中的组合情况是有效果的,并且和Service中的效果是一样的。有人可能会说为什么在Service中就要使用组合呢,因为Service启动Activity必须得加上FLAG_ACTIVITY_NEW_TASK,所以实验的使用实验其他三种标志也必须与这个标记组合。


所以,一般情况下不要依赖使用标记,这个产生的效果不是很好。请在配置文件中配置。












猜你喜欢

转载自blog.csdn.net/sinat_31311947/article/details/61919603