必威体育Betway必威体育官网
当前位置:首页 > IT技术

Android Intent.FLAG_ACTIVITY_NEW_TASK的个人理解

时间:2019-05-31 21:44:05来源:IT技术作者:seo实验室小编阅读:87次「手机版」
 

flag_activity_new_task

首先分四部曲简单做一下说明

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类的结构图

这里写图片描述

在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

相关阅读

对Java中反射机制的理解

简单的说,反射机制就是在程序的运行过程中被允许对程序本身进行操作,比如自我检查,进行装载,还可以获取类本身,类的所有成员变量和方法

Java中接口作用深入理解

关于Java中接口作用的深入理解。这是个很容易遇到的问题吧。 / 2019/3/1 补充 : 接口的存在也是为了弥补类无法多继承的缺点,假设

初学者关于贝叶斯纳什均衡各类符号的一点理解

转载于:https://www.cnblogs.com/xuanlvshu/p/10349192.html

textContent和innerText以及innerHTML的区别,结合demo

先看看下面这个demo,不言自明: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</titl

从Salesforce看,如何理解并设计CRM系统?

最近由于工作所需,为公司的销售团队设计了一套内部使用的CRM销售管理系统。为了设计好该类型的产品,特地去研究并分析了该领域的巨

分享到:

栏目导航

推荐阅读

热门阅读