Activity: launchMode 和 Intent.FLAG_ACTIVITY_CLEAR_TOP
Activity 的 launchMode:
1. standard: 标准模式
这种启动模式为标准模式,也是默认模式。每当我们启动一个Activity,系统就会相应的创建一个实例,不管这个实例是否已经存在。这种模式,一个栈中可以有多个实例,每个实例也都有自己的任务栈。而且是谁启动了此Activity,那么这个Activity就运行在启动它的Activity所在的栈中。
例:有Activity 1 --> Activity 1 -> Activity 1-> Activity 1 -> Activity 1
Logcat:
-- ::28.937 -/? I/xp.chen: onCreate: Activity
-- ::29.944 -/? I/xp.chen: onCreate: Activity
-- ::30.527 -/? I/xp.chen: onCreate: Activity
-- ::30.978 -/? I/xp.chen: onCreate: Activity
-- ::31.332 -/? I/xp.chen: onCreate: Activity
2. singleTop:栈顶复用模式
这种启动模式下,如果要启动的Activity已经处于栈的顶部,那么此时系统不会创建新的实例,而是直接打开此页面,同时它的onNewIntent()方法会被执行,我们可以通过Intent进行传值,而且它的onCreate(),onStart()方法不会被调用,因为它并没有发生任何变化。
3. singleTask:栈内复用模式
在这个模式下,如果栈中存在这个Activity的实例就会复用这个Activity,不管它是否位于栈顶,复用时,会将它上面的Activity全部出栈,因为singleTask本身自带clearTop这种功能。并且会回调该实例的onNewIntent()方法。其实这个过程还存在一个任务栈的匹配,因为这个模式启动时,会在自己需要的任务栈中寻找实例,这个任务栈就是通过taskAffinity属性指定。如果这个任务栈不存在,则会创建这个任务栈。不设置taskAffinity属性的话,默认为应用的包名。
例:有Activity 1 --> Activity 2 -> Activity 3-> Activity 4 -> Activity 5 -> Activity 1, 其中Activity 1 设置成singleTask属性,在Activity5中设置跳转到Activity 1.
Logcat:
-- ::07.415 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::10.476 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::11.105 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::11.714 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::12.653 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::15.388 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::15.395 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::15.403 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::15.424 -/com.yongdaimi.android.androidapitest I/xp.chen: onNewIntent: Activity
-- ::15.698 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
可以看到在这种模式下,Activity 2 ~ Activity 5都会被销毁(包括Activity 5), 然后会调用Activity 1的onNewIntent()方法。利用这种模式的特性,可以实现退出应用,比如在Activity 5启动Activity时,传入一个参数:
public void next(View view) {
Intent intent = new Intent(getApplicationContext(), LaunchMode1Activity.class);
intent.putExtra(LaunchMode1Activity.EXTRA_FINISH, );
startActivity(intent);
}
然后在Activity 1的onNewIntent()方法中做处理:
@Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
Log.i("xp.chen", "onNewIntent: 1 Activity");
int intExtra = intent.getIntExtra(EXTRA_FINISH, -1);
if (intExtra == 0) finish();
}
运行Logcat如下:
2019-09-19 10:51:11.911 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: 1 Activity
2019-09-19 10:51:13.419 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: 2 Activity
2019-09-19 10:51:13.848 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: 3 Activity
2019-09-19 10:51:14.385 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: 4 Activity
2019-09-19 10:51:16.874 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: 5 Activity
2019-09-19 10:51:18.691 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: 2 Activity
2019-09-19 10:51:18.698 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: 3 Activity
2019-09-19 10:51:18.706 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: 4 Activity
2019-09-19 10:51:18.725 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onNewIntent: 1 Activity
2019-09-19 10:51:19.226 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: 1 Activity
2019-09-19 10:51:19.265 16700-16700/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: 5 Activity
4. singleInstance:单实例模式
很多资料都直接说这种模式的Activity 会单独占用一个任务栈,即整个系统中就这一个实例,同样也是栈内复用,后续的请求均不会创建新的Activity实例,除非这个特殊的任务栈被销毁了,感觉说的很抽象,那它跟singleTask有什么区别呢?
例:有Activity 1 --> Activity 2 -> Activity 3-> Activity 4 -> Activity 5 -> Activity 1 , 其中Activity 1 设置成singleInstance属性,在Activity5中设置跳转到Activity 1, 在Activity 5中重写它的onStart()和onStop()方法,并且在从Activity 5跳转到Activity 1之后,再次点击Activity1的跳转按钮(本来默认是跳转到Activity2的),然后再按返回键,观察结果:
Logcat:
-- ::33.686 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::36.620 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::37.246 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::37.958 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::38.748 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::38.750 -/com.yongdaimi.android.androidapitest I/xp.chen: onStart: Activity
-- ::40.490 -/com.yongdaimi.android.androidapitest I/xp.chen: onNewIntent: Activity
-- ::40.956 -/com.yongdaimi.android.androidapitest I/xp.chen: onStop: Activity
-- ::48.412 -/com.yongdaimi.android.androidapitest I/xp.chen: onStart: Activity
-- ::52.911 -/com.yongdaimi.android.androidapitest I/xp.chen: onStop: Activity
-- ::52.912 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::53.676 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::54.905 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::56.857 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::59.147 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
这次的Logcat有些怪异,大概说明一下:
我先是依次从Activity1 点到 Activity 5, 注意到从Activty 1到Activity2的过渡动画发生了改变,与Activity2 跳转到Activity3的动画不同,另外因为在Activity 5 新加了个 onStart() 方法,所以这次log上也有所体现:
-- ::33.686 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::36.620 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::37.246 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::37.958 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::38.748 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
2019-09-19 11:09:38.750 18700-18700/com.yongdaimi.android.androidapitest I/xp.chen: onStart: 5 Activity
当停留在Activity 5时,我再次点击跳转(默认行为是跳转到Activity1, 它的launchMode是singleInstance),注意到此时并未重新调用Activity1的onCreate()方法,而是调用了它的 onNewIntent() 方法,同时调用了Activity 5的 onStop() 方法,因为Activity 5已不再可见。
2019-09-19 11:09:40.490 18700-18700/com.yongdaimi.android.androidapitest I/xp.chen: onNewIntent: 1 Activity
2019-09-19 11:09:40.956 18700-18700/com.yongdaimi.android.androidapitest I/xp.chen: onStop: 5 Activity
此时到达了Activity 1界面,我在Activity1界面再次点击跳转(注意此时的默认行为是跳转到Activity 2), 但是它没有像我预想的那样跳转到Activity 2, 而是直接显示Activity 5, 所以此时显示Activity 5的onStart()方法:
-- ::48.412 -/com.yongdaimi.android.androidapitest I/xp.chen: onStart: Activity
最后我在Activity 5界面连续点击返回键,注意到相关的Activity 也会一 一的被关闭。
-- ::52.911 -/com.yongdaimi.android.androidapitest I/xp.chen: onStop: Activity
-- ::52.912 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::53.676 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::54.905 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::56.857 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::59.147 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
总结:与singleTask不同,当从Activity 5再次点击回到Activity1的时候,Activity2,3,4,5 都不会销毁,但都会调用Activity 1的 onNewIntent()方法。
5.FLAG_ACTIVITY_CLEAR_TOP
之所以会提到这个,是因为早期曾经在项目里看到别人用这个Flag来关闭和退出应用,且从Google的说明上看,它与singleTask mode有一定的相似性:都能清除目标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. 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(). 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. See Tasks and Back Stack for more information about tasks.
那么它与singleTask到底有何区别?还是这个例子:
例:有Activity 1 --> Activity 2 -> Activity 3-> Activity 4 -> Activity 5 -> Activity 1,将Activity1的launch mode 删除,然后在Activity5中修改其跳转到Activity1时的代码,为跳转Intent增加这个Flag: Intent.FLAG_ACTIVITY_CLEAR_TOP :
public void next(View view)
{
Intent intent = new Intent(getApplicationContext(), LaunchMode1Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
Logcat:
-- ::08.704 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::10.749 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::11.131 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::11.495 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::11.808 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::12.657 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::12.665 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::12.671 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
2019-09-19 13:20:12.690 11308-11308/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: 1 Activity
2019-09-19 13:20:12.725 11308-11308/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: 1 Activity
-- ::13.016 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
注意到,与上面的singleTask相同的是,都会销毁掉Activity 2 ~ Activity 5之间的所有Activity (包括Activity5), 但是Activity 1却会重新创建。那么这与Google的说明不一样呀,Google貌似说会调用 onNewIntent() 方法什么的,如何理解Google的这段说明文字?其实Google也说明了:
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. 上面示例中当前运行的Ativity B实例将在它的onNewIntent()方法中接收您从此处开始的新intent, 或者本身已被finish掉并重新使用这个intent来restart。(翻译的不好,我理解的大概如此) 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(). 如果它已将它的启动模式声明为“multiple”(默认值)并且您没有在同一意图中设置FLAG_ACTIVITY_SINGLE_TOP,那么它将被finish并重新创建; 对于所有其他启动模式或如果设置了FLAG_ACTIVITY_SINGLE_TOP,则此Intent将被传递到当前实例的onNewIntent()。
大概意思就是说如果没有同时设置 FLAG_ACTIVITY_SINGLE_TOP 那么目标Activity将会被finish并重新创建,如果同时设置了 FLAG_ACTIVITY_SINGLE_TOP ,那么会将intent传递到目标Activity的 onNewIntent() 方法。那好吧,修改Activity 5 跳转到 Activity 1的代码:
public void next(View view)
{
Intent intent = new Intent(getApplicationContext(), LaunchMode1Activity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
增加上面所说的那个Flag, 同样执行Activity 1 --> Activity 2 -> Activity 3-> Activity 4 -> Activity 5 -> Activity 1操作:
Logcat:
-- ::06.774 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::07.556 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::08.042 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::08.448 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::08.921 -/com.yongdaimi.android.androidapitest I/xp.chen: onCreate: Activity
-- ::09.952 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::09.961 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::09.972 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
-- ::09.991 -/com.yongdaimi.android.androidapitest I/xp.chen: onNewIntent: Activity
-- ::10.271 -/com.yongdaimi.android.androidapitest I/xp.chen: onDestroy: Activity
果然,经过这种方式修改后,其展示的行为与singleTask 保持一致。
综上,可以利用singleTask和FLAG_ACTIVITY_CLEAR_TOP 的这种特性来关闭和退出应用。
参考链接:
1. Android中Activity的启动模式(LaunchMode)和使用场景
Activity: launchMode 和 Intent.FLAG_ACTIVITY_CLEAR_TOP的更多相关文章
- 关于Activity启动模式(launchMode)和intent设置测试后 发现和网上说的不符 是不是我错了 求解
看了很多关于Activity启动模式(launchMode)和intent设置intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);发现网上说的和我测试结果 ...
- Android Activity launchMode研究
Android Activity launchMode研究 Activity的Launch mode一共有四种: standard, singleTop, singleTask, singleInst ...
- ActivityGroup相关--getLocalActivityManager() 以及intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)用法
ActivityGroup简介 1.ActivityGroup的核心就是继承了该类,能够通过getLocalActivityManager()得到一个LocalActivityManager 如,Lo ...
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)用法
如果已经启动了四个Activity:A,B,C和D.在D Activity里,我们要跳到B Activity,同时希望C finish掉,可以在startActivity(intent)里的inten ...
- 【转】Android 关闭多个视图Intent.FLAG_ACTIVITY_CLEAR_TOP用法
如果已经启动了四个Activity:A,B,C和D.在D Activity里,我们要跳到B Activity,同时希望C finish掉, 可以在startActivity(intent)里的inte ...
- ActivityGroup、TabHost之子页面不刷新——getLocalActivityManager() 以及intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)用法
TabHost继承自ActivityGroup,以下不再单独列出. ActivityGroup在第一次创建的时候会完整的执行子Activity或子view的生命周期,但在从其他子activity或子v ...
- Activity之间使用intent传递大量数据带来问题总结
转载:大飞 http://blog.csdn.net/rflyee/article/details/47441405 Activity之间使用Parcel传递大量数据产生的问题. Activity ...
- Activity生命周期,Activity传值(Intent)
生命周期: 从出生到死亡 Activity生命周期的7个方法和3个循环 onCreate() 创建时调用onRestart() 不可见到可见时调用onStart() 用户可见时调用onResume() ...
- Activity间通过Intent交互及系统服务调用
I. 实验目的通过本实验理解Android开发框架中最核心程序部件Activity间通过Intent交互的原理,掌握通过Intent传递参数和系统服务调用的方法,并通过实验中的3个具体的实验内容加深理 ...
随机推荐
- 搭建cas 服务器
https://blog.csdn.net/oumuv/article/details/84306361 记得添加数据库驱动 https://blog.csdn.net/zhouzhiwengang/ ...
- win10 64下anaconda4.2.0(python3.5)
python环境:win10 64下anaconda4.2.0(python3.5).安装tensorflow过程是在Anaconda Prompt中进行安装 1:打开Anaconda Prompt ...
- K8S集群证书已过期且etcd和apiserver已不能正常使用下的恢复方案
在这种比较极端的情况下,要小心翼翼的规划和操作,才不会让集群彻底死翘翘.首先,几个ca根证书是10年期,应该还没有过期.我们可以基于这几个根证书,来重新生成一套可用的各组件认证证书. 前期,先制定以下 ...
- python 单元测试(unittest)
自动化测试在各大互联网公司全面铺开,那么针对于自动化测试好的设计思想有哪些呢?.....今天我们共同探讨下Unittest之数据驱动(DDT是 “Data-Driven Tests”的缩写). 对于接 ...
- Python语言程序设计(1)--实例1和基本知识点
记录慕课大学课程<Python语言程序设计>的学习历程. 实例1:温度转换 #温度转换TempStr = input("请输入带有符号的温度值:") #TempStr是 ...
- npm run build 时的 warning
entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit ...
- html页面标记 点击目录跳转到页面相应位置 简易回到顶部
html页面标记 点击目录跳转到页面相应位置 简易回到顶部 参考博客:
- IDEA 中tomcat图片储存和访问虚拟路径(图片和程序分家)
本文链接:https://blog.csdn.net/qq_36481052/article/details/78813213 **前段时间,遇到了图片已经储存了文件中也显示有图片,但就是死活访问不到 ...
- 项目读取数据,一直出现 Closing connections idle longer than 30 SECONDS,卡死现象
项目读取数据,一直出现 Closing connections idle longer than 30 SECONDS,卡死现象. 我的是在读取oracle数据的时候出现这种错误. 可以参考这篇文章 ...
- RocketMQ部分消息消费不到的问题
在企业项目中,利用RocketMQ接收数据,存库. 由于是第一次在项目中具体的使用RocketMQ,一直采坑. 1.发现问题:在最终的联调过程中,并发压测,订单数据丢失,同一时刻,oms推送900+的 ...