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年7月17日 下午2:36
下一篇 2022年7月17日 下午2:36


相关推荐

  • 【目录】python全栈工程师

    【目录】python全栈工程师第一阶段:Python语言核心编程1.Python核心–2048游戏核心算法2.面向对象–天龙八部游戏技能系统3.Python高级–集成操作框架项目:2048游戏第二阶段:

    2022年7月5日
    28
  • 结构体 变迁

    结构体 变迁

    2021年12月6日
    43
  • RC微分积分电路/RC滤波电路/RC脉冲分压器/RC耦合电路

    RC微分积分电路/RC滤波电路/RC脉冲分压器/RC耦合电路在模拟及脉冲数字电路中 常常用到由电阻 R 和电容 C 组成的 RC 电路 在些电路中 电阻 R 和电容 C 的取值不同 输入和输出关系以及处理的波形之间的关系 产生了 RC 电路的不同应用 下面分别谈谈微分电路 积分电路 耦合电路 脉冲分压器以及滤波电路 1 RC 微分电路 如图 1 所示 电阻 R

    2026年3月18日
    1
  • vsftp用户名密码配置_win10ftp服务器设置用户名和密码

    vsftp用户名密码配置_win10ftp服务器设置用户名和密码huangyandong于2011-05-1013:06:11发表:打开vsftpd的配置文件,redhat的配置文件默认为/etc/vsftpd.conf:要想使用本地用户登录的话则只需更改下列选项local_enable改为YESchroot_local_user=YES#当设置为YES时,本地用户登录后就自动转到他们的用户主目录中去。#注意!:该选项用安全问题,特别是当用户有上传文…

    2026年3月3日
    7
  • Spring Boot Configuration Annotation Processor not configured 问题解决

    Spring Boot Configuration Annotation Processor not configured 问题解决问题背景 进行 SpringBoot 配置文件部署时 发出警告 SpringBootCo 但是不影响运行 问题解决方案 在 pom xml 文件中引入依赖 dependency groupId org springframew boot amp l groupId dependency

    2026年3月19日
    1
  • SVM, Softmax损失函数[通俗易懂]

    SVM, Softmax损失函数[通俗易懂]版权声明:本文为博主原创文章,未经博主允许不得转载。目录(?)[+]Deeplearning在计算机视觉方面具有广泛的应用,包括图像分类、目标识别、语义分隔、生成图像描述等各个方面。本系列博客将分享自己在这些方面的学习和认识,如有问题,欢迎交流。在使用卷积神经网络进行分类任务时,往往使用以下几类损失函数:平方误差损失SVM损失s

    2022年6月26日
    33

发表回复

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

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