为什么在子线程里面startActivity需要添加FLAG_ACTIVITY_NEW_TASK

2,402 阅读2分钟

经典讲解

首先分四部曲简单做一下说明
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中,定义了startActivity方法:  public abstract void startActivity(Intent intent);
ContextWrapper继承覆盖了这个方法:
public void startActivity(Intent intent) {
    mBase.startActivity(intent);
}
熟悉Android委托机制的应该知道,这个mBase实际指向的是ContextImpl这个类,我们再来看这个类中的startActivity方法。
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方法。
现在在回到开头,FLAG_ACTIVITY_NEW_TASK从字面上来理解,意思是:把将要启动的Activity放在一个新栈中,既然是新栈,那它的taskId和启动它的Activity所在的taskId肯定是不一样的。
最后做一下总结:
1.在Activity上下文之外启动Activity需要给Intent设置FLAG_ACTIVITY_NEW_TASK标志,不然会报异常。
2.加了该标志,如果在同一个应用中进行Activity跳转,不会创建新的Task,只有在不同的应用中跳转才会创建新的Task

参考网址:blog.csdn.net/u010389391/…