Android Intent.FLAG_ACTIVITY_NEW_TASK的个人理解「建议收藏」

Android Intent.FLAG_ACTIVITY_NEW_TASK的个人理解「建议收藏」首先分四部曲简单做一下说明1.What(是什么):Intent类中的一个静态标志属性publicstaticfinalintFLAG_ACTIVITY_NEW_TASK=0x10000000;2.Why(为什么要使用):在特殊情况下,如果不加这个标志,会报错(下文详细说明)3.When(什么时候使用):当调用startActivity启动一个Activity时4.How(如何

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

首先分四部曲简单做一下说明
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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/185318.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • stm32新手入门什么是寄存器_STM32H7寄存器

    stm32新手入门什么是寄存器_STM32H7寄存器小白单片机入门必看,俗话说得好基础不牢地动山摇,要学好单片机一定要熟知底层原理

    2025年9月24日
    6
  • Java中的cas(this关键字java)

    在JDK5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁锁机制存在以下问题:(1)在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。(2)一个线程持有锁会导致其它所有需要此锁的线程挂起。(3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。volatile是不错的机制

    2022年4月14日
    102
  • java softReference 详解 .[通俗易懂]

    java softReference 详解 .[通俗易懂]本文介绍对象的强、软、弱和虚引用的概念、应用。1.对象的强、软、弱和虚引用  在JDK1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及(reachable)状态,程序才能使用它。从JDK1.2版本开始,把对象的引用分为4种级别,从而使程序能更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

    2025年10月6日
    1
  • android 触摸屏事件_android模拟屏幕点击

    android 触摸屏事件_android模拟屏幕点击android中的事件类型分为按键事件和屏幕触摸事件,Touch事件是屏幕触摸事件的基础事件,有必要对它进行深入的了解。一个最简单的屏幕触摸动作触发了一系列Touch事件:ACTION_DOWN->ACTION_MOVE->ACTION_MOVE->ACTION_MOVE…->ACTION_MOVE->ACTION_UP当屏幕中包含一个ViewGroup,而这个ViewGroup又包含

    2025年10月21日
    3
  • 总结进制转换的方法_八进制计算方法

    总结进制转换的方法_八进制计算方法今天朋友去面试,面试官问他八进制转换二进制方式原理,他突然间蒙逼了,在常见的计算机知识当中,这种最基础的知识,常常会被人给忘记,所以今天我来写一篇进制转换的总结,来复习巩固一下。本文参考百度经验(https://jingyan.baidu.com/article/495ba84109665338b30ede98.html),如有侵权,请通知删除先讲一下定义吧,进制也就是进制位,对于接触过电脑的…

    2022年8月31日
    4
  • centos 7如何将 网卡ens33 修改成 eth0「建议收藏」

    centos 7如何将 网卡ens33 修改成 eth0「建议收藏」文章目录linux网卡名称命名命名规则修改eth0方法linux网卡名称命名命名规则CENTOS6的网卡命名方式它会根据情况有所改变而非唯一且固定,在CENTOS6之前,网络接口使用连续号码命名:eth0、eth1等,当增加或删除网卡时,名称可能会发生变化CENTOS7命名方式采用dmidecode采集命名方案,以此来得到主板信息;它可以实现网卡名字永久唯一化(dmidecode这个命令可以采集有关硬件方面的信息)对网络设备的命名方式:1)如果Firmware(固件)或B

    2025年5月22日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号