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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【愚公系列】2022年02月 wireshark系列-数据抓包分析之DHCP协议

    【愚公系列】2022年02月 wireshark系列-数据抓包分析之DHCP协议实验步骤一获取DHCP数据包在windows平台上获取DHCP数据包在windows平台上,可以使用两种简单的方法实现,其原理一样。(1)在cmd上,使用ipconfig命令来获取。执行完上述命令后,将释放当前使用的地址信息。重新获取地址信息,执行命令如下执行完上面的命令后,将重新获取地址信息。在获取地址时,将会经过上面讲述的DHCP的4个阶段。这样,我们就能获取到DHCP数据包了。(2)通过禁用和启用网卡获取DHCP数据包在windows平台上,也可以通过禁用和启用网卡获取DHCP数

    2022年5月23日
    45
  • opengrok搭建[通俗易懂]

    opengrok搭建[通俗易懂]前序OpenGrok是一个快速,便于使用的源码搜索引擎与对照引擎,它能够帮助我们快速的搜索、定位、对照代码树。一般常用于大型的项目中,比如Android系统源码。我也是刚来公司后才发现有这个东西的,在此自己也搭建一套,方便在家里也可以查看源码。因为是查看自己定制的系统源码所以要搭这个,如果只是查看AOSP的官方源码推荐一个网站:http://androidxref.com/环境OS:Debian

    2022年4月27日
    64
  • ❤️肝下25万字的《决战Linux到精通》笔记,你的Linux水平将从入门到入魔❤️【建议收藏】[通俗易懂]

    ❤️肝下25万字的《决战Linux到精通》笔记,你的Linux水平将从入门到入魔❤️【建议收藏】[通俗易懂]文章目录操作系统的发展史UnixMinixLinux操作系统的发展Minix没有火起来的原因Linux介绍Linux内核&发行版Linux内核版本Linux发行版本类Unix系统目录结构Linux目录用户目录命令行基本操作命令使用方法查看帮助文档helpman(manual)tab键自动补全history游览历史命令行中的ctrl组合键Linux命令权限管理列出目录的内容:ls显示inode的内容:stat文件访问权限修改文件权限:chmod修改文件所有者:chown修改文件所属组:chgrp文件.

    2022年6月1日
    23
  • C语言字符串匹配函数建议收藏

    C语言字符串匹配函数,保存有需要时可以用:1#include2#include3#include4#include5#include67/*8pattern:9pos

    2021年12月20日
    45
  • 【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树「建议收藏」

    【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树「建议收藏」【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树

    2022年4月21日
    37
  • 由华为裁员传闻引发的思考:年轻人如何避免中年危机?「建议收藏」

    由华为裁员传闻引发的思考:年轻人如何避免中年危机?「建议收藏」看到这个话题,让我想起来之前在知乎上看到的一句话,找了半天当时的截图,没找到。最后在QQ留言板上找到了:这句话确实是让人细思极恐,时间再也没有童年那么漫长了,变得越来越快。20岁时,你可以没有钱,买不起iphone4送给女朋友。总说莫欺少年穷,是因为你有大把的未来去提高自己,同时提高自己的经济实力。不然的话。30岁时,你舍不得给老婆买iphone8。40岁时,你的妻子就会因为压力迅速苍老,然后你的…

    2022年7月18日
    41

发表回复

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

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