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模式的效果。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • rar.exe命令行参数与示例

    rar.exe命令行参数与示例

  • 用最简单的一个例子看maven冲突的解决办法

    用最简单的一个例子看maven冲突的解决办法

    2020年11月20日
  • SSRF漏洞原理解析[通俗易懂]

    SSRF漏洞原理解析[通俗易懂]文章目录0x01基础知识1、SSRF漏洞简介:2、主要攻击方式:3、漏洞形成原理:4、漏洞的危害:0x02漏洞检测1、漏洞验证:2、漏洞的可能出现点:0x03绕过方法:1、绕过限制为某种域名:2、绕过限制请求IP不为内网地址:3、限制请求只为http协议:0x04漏洞利用1、产生漏洞的函数:2、漏洞靶场:0x05如何防御SSRF0x01基础知识1、SSRF漏洞简介:SSRF全称:Server-SideRequestForgery,即服务器端请求伪造,是一个由攻击者构造请求在目标服务

  • 元学习、迁移学习、对比学习、自监督学习与少样本学习的关系解读

    元学习、迁移学习、对比学习、自监督学习与少样本学习的关系解读文章目录前言一、对比自监督学习与FSL1.对比学习与自监督学习2.自监督学习与FSL二、元学习与FSL1.元学习是什么2.元学习与FSL三、迁移学习与FSL1.迁移学习2.迁移学习与FSL总结前言本人的研究方向是少样本图像分类,在阅读论文时会遇到很多元学习、迁移学习这样的名词,这些词在不同的论文中关系仿佛都不一样,人们的说法也不统一。因此在此记录一下自己的逻辑,希望不再混乱了~还有对比学习和自监督学习,最近自己也在看,并且和少样本学习(FSL)相关,就一起放在这里。文章中出现的ppt截图是自己讲组

  • vue webpak版本 查看_vue版本以及webpack版本

    vue webpak版本 查看_vue版本以及webpack版本vue作为大前端的主流框架更新速度也是极快。那么vue的更新会有哪些问题呢?最近在搭建vue框架的时候发现由于vue版本的快速迭代已经与原本般配的webpack产生了隔阂。webpack作为大前端的主流打包工具如果与之不兼容,会有越来越多的麻烦事情。经过反复测试,得出结论一篇vue与webpack最佳拍档组合版本号公布。npminitnpminstallwebpack@3.10.0v…

  • GB28181服务器_GB28181收费吗

    GB28181服务器_GB28181收费吗CarEye开发GB28181服务器有将近两年时间了,早期我们用纯C++开发了一个GB28181视频服务期,对外的接口是基于MQ协议的。这样开发出来的服务器主要有几个问题。1.SIP服务器和流媒体服务器是绑定在一个进程中的,因为没有分离,造成了视频处理和SIP服务器只能在一台服务器上运行,既不能打到GB28181协议的构架要求。也造成无法使用负载均衡的功能。2.对外接口采用了MQ通信方式。虽然MQ消息处理实时,对一些数据处理,如报警,对讲等。但MQ本身是重量级构建,不方便一些应用场景快速构建

发表回复

您的电子邮箱地址不会被公开。

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