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)
blank

相关推荐

  • minhash算法_verlet算法

    minhash算法_verlet算法背景如何设计一个比较两篇文章相似度的算法?可能你会回答几个比较传统点的思路:一种方案是先将两篇文章分别进行分词,得到一系列特征向量,然后计算特征向量之间的距离(可以计算它们之间的欧氏距离、海明距离或者夹角余弦等等),从而通过距离的大小来判断两篇文章的相似度。另外一种方案是传统hash,我们考虑为每一个web文档通过hash的方式生成一个指纹(fingerprint)。下面,我们来分析下这两种方法…

  • rinetd小记「建议收藏」

    官网:http://www.boutell.com/rinetd/下载地址:http://www.boutell.com/rinetd/http/rinetd.tar.gz编译安装:对于Windows,包rinetd.tar.gz已包含了编译好的可执行程序文件rinetd.exe,也可以使用VC(如VC6.0)去重新编译。对于Linux,只需要将包rin…

  • 分布式文件存储—fastDFS

    分布式文件存储—fastDFS简单了解:•FastDFS是一个轻量级的开源分布式文件系统•解决了大容量文件存储和高并发访问的问题,文件存取时实现了负载均衡•FastDFS实现了软件方式的RAID,可以使用廉价的IDE硬盘进行存储•支持存储服务器在线扩容•支持相同内容的文件只保存一份,节约磁盘空间,配合FastDHT进行文件上传去重•特别适合大中型网站使用,用来存储资源文件(图片,文档,音频,

  • oracle dba和sysdba的区别

    oracle dba和sysdba的区别之前老是把dba和sysdba混为一体,今天看到论坛在讨论两者的区别,特记录如下:SYSDBA不是权限,当用户以SYSDBA身份登陆数据库时,登陆用户都会变成SYS。sysdba身份登陆可以打开,

  • es6箭头函数详解_es6的新特性

    es6箭头函数详解_es6的新特性ES6标准新增了一种新的函数:ArrowFunction(箭头函数)。基础语法通常函数的定义方法varfn1=function(a,b){returna+b}functionfn2(a,b){returna+b}使用ES6箭头函数语法定义函数,将原函数的“function”关键字和函数名都删掉,并使用“=>”连接参数…

  • Android 面试精华题目总结

    Android 面试精华题目总结下面的题目都是楼主在android交流群大家面试时遇到的,如果大家有好的题目或者好的见解欢迎分享,楼主将长期维护此帖。1、请解释下在单线程模型中Message,Handler,MessageQueue,Lopper之间的关系。2、如果有个100M大的文件,需要上传至服务器中,而服务器form表单最大只能上传2M,可以用什么方法。3、内存溢出和内存泄漏有什么区别

发表回复

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

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