FLAG_ACTIVITY_CLEAR_TOP和singleTask的区别

FLAG_ACTIVITY_CLEAR_TOP和singleTask的区别Activity的Flags的设置,可以让Activity的运行具有一些特殊的特性,比如有些可以产生和启动模式相同或相似效果的,还有比如Activity在非前台的时候,也不会保存后台的历史列表中。本文重点分析FLAG_ACTIVITY_CLEAR_TOP,也简单介绍一下其它几个常用的Flag以及使用场景FLAG_ACTIVITY_NEW_TASK将Activity指定为singleTas…

大家好,又见面了,我是你们的朋友全栈君。

Activity的Flags的设置,可以让Activity的运行具有一些特殊的特性,比如有些可以产生和启动模式相同或相似效果的,还有比如Activity在非前台的时候,也不会保存后台的历史列表中。

本文重点分析FLAG_ACTIVITY_CLEAR_TOP,也简单介绍一下其它几个常用的Flag以及使用场景

  • FLAG_ACTIVITY_NEW_TASK
    将Activity指定为singleTask的启动模式,效果和在xml中指定启动模式是一样的,同时指定的话,java代码设置高于xml文件配置。

  • FLAG_ACTIVITY_SINGLE_TOP
    将Activity指定为singleTop启动模式,效果和在xml中指定启动模式是一样的,同时指定的话,java代码设置高于xml文件配置。

  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
    具有此标记位的ACTIVITY不会出现在历史ACTIVITY的列表中,当某些情况,我们不希望用户通过历史列表回到我们的ACTIVITY的时候,这个标记比较有用。他等同于在xml指定ACTIVITY的属性android:excludeFromRecents=“true”。

    关于这个属性,我在早期做开发的时候,还真有这么一个使用场景,实现的一种类似插件化的方案,就是借助这个属性的设置去完成的。

    场景大概是这样:我们的app里面需要一个视频编辑的功能,但是视频编辑呢,大家都知道要使用FFMPEG的库,这个包体大小10M以上,但是我们的主app只有5M,突然增加10M,对市场渠道投放的单本会影响很大。为了解决这个问题吧,只能插件化,当时呢,我们并没有使用什么插件化方案,而是单独把频编辑工具打包成apk,然后主apk用户注册成功后,进行下载安装。这样用户在使用我们的app的时候,如果也打开了视频编辑工具Apk,那么Activity的历史列表中,也会存在。
    为了解决这个问题,我们就把视频编辑工具的apk的Activity设置成这个属性。

  • FLAG_ACTIVITY_CLEAR_TOP
    具有此标记的Activity被启动后,位于其上的所有Activity都会出栈。但是这个描述是字面含义,我们需要真正理解它。

    接下来我们看一下官方的解释:
    If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.

    For example, consider a task consisting of the activities: A, B, C, D. If D calls startActivity() with an Intent that resolves to the component of activity B, then C and D will be finished and B receive the given Intent, resulting in the stack now being: A, B.

    这段大概描述的意思是如图所示:
    FLAG_ACTIVITY_CLEAR_TOP和singleTask的区别

    但是,“instead of launching a new instance of that activity” 说明,结果集里面的B已经不在是上一个任务栈ABCD里面的B实例了(后面会有代码验证)。

    The currently running instance of activity B in the above example will either receive the new intent you are starting here in its onNewIntent() method, or be itself finished and restarted with the new intent. If it has declared its launch mode to be “multiple” (the default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created; for all other launch modes or if FLAG_ACTIVITY_SINGLE_TOP is set then this Intent will be delivered to the current instance’s onNewIntent().

    这段的解释:上面例子中运行的B activity既可以在onNewIntent()中接收新的Intent,也可以将自己finish掉然后使用新的Intent重启。如果在它的launch mode中设置了”multiple”(默认,从源码中可以看到默认就是standard标准启动模式),并且intent中没有设置 FLAG_ACTIVITY_SINGLE_TOP 标志,那它就会被finish掉然后重新创建。如果是其它的launchMode或者是设置了FLAG_ACTIVITY_SINGLE_TOP 属性,那就会使用现有的实例的OnNewIntent()方法来接受Intent。

    这里面,我们接下来写一个实例
    FirstActivity.java

        @Override
        protected void onCreate(Bundle savedInstanceState) { 
         
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_first);
            findViewById(R.id.btn_next).setOnClickListener(new View.OnClickListener() { 
         
                @Override
                public void onClick(View v) { 
         
                    startActivity(new Intent(FirstActivity.this,SecondActivity.class));
                }
            });
        }
    }
    

    SecondActivity.java

    public class SecondActivity extends AppCompatActivity { 
         
    
        String TAG="Live"+this.getClass().getSimpleName();
        @Override
        protected void onCreate(Bundle savedInstanceState) { 
         
            super.onCreate(savedInstanceState);
            Log.i(TAG,"===>onCreate");
            setContentView(R.layout.activity_second);
            findViewById(R.id.btn_to_third).setOnClickListener(new View.OnClickListener() { 
         
                @Override
                public void onClick(View v) { 
         
                    startActivity(new Intent(SecondActivity.this,ThirdActivity.class));
                }
            });
        }
    
        @Override
        protected void onNewIntent(Intent intent) { 
         
            super.onNewIntent(intent);
            Log.i(TAG,"===>onNewIntent");
    
        }
        @Override
        protected void onDestroy() { 
         
            super.onDestroy();
            Log.i(TAG,"===>onDestroy");
      
    

    ThirdActivity.java

    public class ThirdActivity extends AppCompatActivity { 
         
        String TAG="Live"+this.getClass().getSimpleName();
        @Override
        protected void onCreate(Bundle savedInstanceState) { 
         
            super.onCreate(savedInstanceState);
            Log.i(TAG,"===>onCreate");
            setContentView(R.layout.activity_third);
            findViewById(R.id.btn_to_second).setOnClickListener(new View.OnClickListener() { 
         
                @Override
                public void onClick(View v) { 
         
                    Intent intent=new Intent(ThirdActivity.this,SecondActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    startActivity(intent);
                }
            });
        }
        @Override
        protected void onNewIntent(Intent intent) { 
         
            super.onNewIntent(intent);
            Log.i(TAG,"===>onNewIntent");
    
        }
    
        @Override
        protected void onDestroy() { 
         
            super.onDestroy();
            Log.i(TAG,"===>onDestroy");
        }
    }
    

    此时清单文件都是默认配置,从1->2->3, 3->2(设置了FLAG_ACTIVITY_CLEAR_TOP),打印的结果如下:

    4130-4130/com.hym.laucher2 I/LiveSecondActivity: ===>onCreate
    4130-4130/com.hym.laucher2 I/LiveThirdActivity: ===>onCreate
    4130-4130/com.hym.laucher2 I/LiveSecondActivity: ===>onDestroy
    4130-4130/com.hym.laucher2 I/LiveSecondActivity: ===>onCreate
    4130-4130/com.hym.laucher2 I/LiveThirdActivity: ===>onDestroy

    的确创建了新的SecondActivity。修改一下清单文件,设置SecondActivity为singleTop的启动模式:

    <activity android:name=".SecondActivity" android:launchMode="singleTop"/>
    

    再重复上述的交互操作

    4523-4523/com.hym.laucher2 I/LiveSecondActivity: ===>onCreate
    4523-4523/com.hym.laucher2 I/LiveThirdActivity: ===>onCreate
    4523-4523/com.hym.laucher2 I/LiveSecondActivity: ===>onNewIntent
    4523-4523/com.hym.laucher2 I/LiveThirdActivity: ===>onDestroy

    此时并没有创建新的SecondActivity的实例。接着看最后一段官方文档的解释:

    This launch mode can also be used to good effect in conjunction with FLAG_ACTIVITY_NEW_TASK: if used to start the root activity of a task, it will bring any currently running instance of that task to the foreground, and then clear it to its root state. This is especially useful, for example, when launching an activity from the notification manager。

    我设计一段代码,快速验证上述描述所说明的问题,这是代码运行后,通过db shell dumpsys activity activities当前的任务栈:

    FLAG_ACTIVITY_CLEAR_TOP和singleTask的区别

    case1:Task2SecondActivity以FLAG_ACTIVITY_CLEAR_TOP方式启动SecondActivity,且SecondActivity默认设置。

    FLAG_ACTIVITY_CLEAR_TOP和singleTask的区别

    Case2:Task2SecondActivity以FLAG_ACTIVITY_CLEAR_TOP方式启动SecondActivity,且SecondActivity设置了singleTask启动模式。

    FLAG_ACTIVITY_CLEAR_TOP和singleTask的区别

    正如官方文档所说,这种启动模式也可以与 FLAG_ACTIVITY_NEW_TASK 一起使用:如果用来启动一个任务的root activity,它会将这个任务中现在运行的实例调到前台,然后将任务清空至只有根Activity的状态。这很有用,例如要从通知中心里启动一个Activity时。

回顾一下启动模式和Flag设置,我们可以得出下面的结论:

  1. 直接设置Activity的启动模式或者设置Flag的方式,都能达成设计Activity任务栈的一些特殊交互场景。
  2. 二者存在区别,Flag方式的优先级高于启动模式的直接设置方式。
  3. Flag方式设置的范围更广一些,也不完全交叉。Flag的方式,相对灵活,但是也是无法直接通过Flag设置的方式去设置一个Activity具有singleInstance模式的效果。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

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

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


相关推荐

  • idea后端开发必备插件:MybatisCodeHelperPro[通俗易懂]

    idea后端开发必备插件:MybatisCodeHelperPro[通俗易懂]官方文档在这:https://gejun123456.github.io/MyBatisCodeHelper-Pro/#/

    2022年9月21日
    8
  • BigDecimal的加减乘除及比较大小

    BigDecimal的加减乘除及比较大小BigDecimal的加减乘除及比较大小

    2022年4月23日
    64
  • fgc java_内存紧张,FGC停不下来[通俗易懂]

    fgc java_内存紧张,FGC停不下来[通俗易懂]客套话不说了哈,请社区里各路高人,指点以下,有点奔溃了。问题是这样:存储的是监控相关数据。日均7.5亿条数据,副本数1.算上副本,日均新增数据1.8T,只保存2天。查询入口只有UI点击,日pv在100以内(都是有问题才会去看监控)关键是有18台物理机,128G内存,单机双节点。每个节点Heap31G。只能跑一天到2天。。ES版本:1.7.1GC配置比较简单:G1,pause200ms…

    2022年6月19日
    27
  • JVM内存模型(通俗易懂)

    JVM内存模型(通俗易懂)1.什么是jvm?(1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。(2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。(3)JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。2.jdk、jre、jvm是什么关系?(1)JRE(JavaR

    2022年4月28日
    80
  • Python学生信息管理系统课程设计报告_python做的项目管理系统

    Python学生信息管理系统课程设计报告_python做的项目管理系统1.本人第一次学python做出来的,当时满满的成就感,当作纪念!!!!!非常简单,复制即可使用代码块importjson#把字符串类型的数据转换成Python基本数据类型或者将Python基本数据类型转换成字符串类型。deflogin_user():whileTrue:register=input(‘学生姓名:’)try:…

    2022年10月10日
    3
  • Bozz Nuster_Collectivum XXVIII

    Bozz Nuster_Collectivum XXVIII这篇文章主要讲的是在Libprotobuf-mutator与LibFuzzer联合使用的基础上,加上custommutator功能。首先需要明确的是为什么要这么做,那么假设b字段只有为”FUZZ”或”PWN”两个字符的时候才能进入下一个程序分支的情况,当然LibFuzzer也可以在代码覆盖率的加持下进入下一个程序分支,但如果你通过逆向的方式已经知道了这个关键点,难道还需要等LibFuzzer跑出这两个字符串吗?

    2025年11月7日
    3

发表回复

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

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