美文网首页
Android Intent.FLAG_ACTIVITY_NEW

Android Intent.FLAG_ACTIVITY_NEW

作者: KyneMaster | 来源:发表于2022-10-24 14:00 被阅读0次

    首先分四部曲简单做一下说明
    1.What(是什么):Intent类中的一个静态标志属性

    public static final int FLAG_ACTIVITY_NEW_TASK = 0x10000000;
    

    2.Why(为什么要使用):在特殊情况下,如果不加这个标志,会报错(下文详细说明)
    3.When(什么时候使用):当调用startActivity启动一个Activity时
    4.How(如何使用)

    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    

    下面详细说明,首先看一张Context类的结构图


    image.png

    在Context中,定义了startActivity方法

    public abstract void startActivity(Intent intent);
    

    ContextWrapper继承覆盖了这个方法

    @Override
        public void startActivity(Intent intent) {
            mBase.startActivity(intent);
        }
    

    熟悉Android委托机制的应该知道,这个mBase实际指向的是ContextImpl这个类,我们再来看这个类中的startActivity方法

    @Override
        public void startActivity(Intent intent, Bundle options) {
            warnIfCallingFromSystemProcess();
            if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                throw new AndroidRuntimeException(
                        "Calling startActivity() from outside of an Activity "
                        + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                        + " Is this really what you want?");
            }
            mMainThread.getInstrumentation().execStartActivity(
                    getOuterContext(), mMainThread.getApplicationThread(), null,
                    (Activity) null, intent, -1, options);
        }
    

    注意看上面的这段代码:if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0)
    如果intent中没有添加FLAG_ACTIVITY_NEW_TASK这个属性,那么就会报错。
    这也是为什么在Service中调用startActivity和在BroadcastReceiver(静态注册)中通过onReceive传递过来的context.startActivity时(该context类型为ReceiverRestrictedContext,和Service一样,都没有重写startActivity),如果不加FLAG_ACTIVITY_NEW_TASK的话会报如下错误的原因

    "Calling startActivity() from outside of an Activity "
                        + " context requires the FLAG_ACTIVITY_NEW_TASK flag."
                        + " Is this really what you want?"
    

    那到这里可能就有疑问了,为什么在Activity中不加FLAG_ACTIVITY_NEW_TASK调用startActivity时不会报错呢。原因是因为Activity重写了ContextWrapper中的startActivity方法

    @Override
        public void startActivity(Intent intent) {
            this.startActivity(intent, null);
        }
    @Override
        public void startActivity(Intent intent, @Nullable Bundle options) {
            if (options != null) {
                startActivityForResult(intent, -1, options);
            } else {
                // Note we want to go through this call for compatibility with
                // applications that may have overridden the method.
                startActivityForResult(intent, -1);
            }
        }
    
    public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
            if (mParent == null) {
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
    
        }
    

    可以发现,里面是没有加FLAG_ACTIVITY_NEW_TASK判断的。

    现在在回到开头,FLAG_ACTIVITY_NEW_TASK从字面上来理解,意思是:把将要启动的Activity放在一个新栈中,既然是新栈,那它的taskId和启动它的Activity所在的taskId肯定是不一样的。
    但真的是这样吗?来看一个例子
    新建一个应用,MainActivity代码

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent intent = new Intent(this,SecondActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
    
            Log.d("MainActivity的TaskId" , getTaskId() + "");
        }
    
    }
    

    SecondActivity代码

    public class SecondActivity extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_second);
            Log.d("SecondActivity的TaskId" , getTaskId() + "");
        }
    }
    

    代码很简单,在MainActivity的onCreate方法中启动SecondActivity,日志如下

    MainActivity的TaskId: 31
    SecondActivity的TaskId: 31
    

    它们的TaskId竟然是一样的,在同一个栈中,说好的new_task呢?
    原来这个这个属性,还有不少隐藏的信息,它的原则是:设置此状态,首先会查找是否存在和被启动的Activity具有相同的亲和性的任务栈(即taskAffinity,注意同一个应用程序中的activity的亲和性一样),如果有,则直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建一个栈来存放被启动的activity。

    原来如此,因为我们是在同一个应用中进行Activity跳转的,所以它不会创建新的Task。那现在试一下在不同的应用中跳转看看,先创建两个module

    app中的MainActivity代码

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Log.d("app的taskId:", getTaskId() + "");
        }
    
        public void openOtherActivity(View view) {
            Intent intent = new Intent();
            ComponentName componentName = new ComponentName("cn.test.server","cn.test.server.MainActivity");
            intent.setComponent(componentName);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
    }
    

    server中的MainActivity代码

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Log.d("server的taskId:", getTaskId() + "");
        }
    }
    

    日志如下

    app的taskId:: 32
    server的taskId:: 33
    

    终于出现了想要的结果,两个不一样的Task。因为在一个应用中调用另一个应用中的Activity,taskAffinity不一样,就创建了新的Task。
    可以自行试一下不加intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),结果是两个taskId都是一样的

    最后做一下总结:
    1.在Activity上下文之外启动Activity需要给Intent设置FLAG_ACTIVITY_NEW_TASK标志,不然会报异常。
    2.加了该标志,如果在同一个应用中进行Activity跳转,不会创建新的Task,只有在不同的应用中跳转才会创建新的Task

    参考
    1.https://www.cnblogs.com/xiaoQLu/archive/2012/07/17/2595294.html
    2.http://blog.csdn.net/dajian790626/article/details/8520522
    ————————————————
    版权声明:本文为CSDN博主「仰子瞻」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/u010389391/article/details/78558475

    相关文章

      网友评论

          本文标题:Android Intent.FLAG_ACTIVITY_NEW

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