活动的启动模式和intent.setFlags方法中的参数值含义

接触了android四大组件之一 Activity,这么长时间,都没有认真总结一下。今天就总结一下吧。
##活动的启动模式
总得来说活动的启动模式有一下四种:standard, singleTop, singleTask, singleInstance。可以在清单文件中,通过给activity标签指定 android:launchMode 属性来选择启动模式。

先简单的了解一下张图:
这里写图片描述

一:standard 是活动模式默认的启动模式,如果不显示的指定的话,所有活动都会自动使用这种启动模式。对于使用standard模式的活动,系统不会再乎这个活动是否已经在返回栈中存在,每次启动都会去创建该活动的一个新的实例。例如启动activity时为 :A B C D,返回时依次为:D C B A。

原理示意图:
这里写图片描述

二:singleTop 当活动的启动模式指定为singleTop,在启动活动时如果发现该活动已经在返回栈的 栈顶 时,就不会再创建该活动的实例了。可能有人会问了,如果该活动不在返回栈的栈顶时怎么处理呢?很抱歉,不在返回栈的栈顶时,系统会去创建该活动的一个新的实例。那有没有只要是在返回栈中的活动,就不会再去创建该活动的实例,的启动模式呢?当然是有啦,看看第三种启动模式。

三:singleTask 模式可以很好地解决重复创建栈顶活动的问题。当活动指定为 singleTask 模式后,每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。注意:如果检查到返回栈中存在该活动的实例,会回调该方法:onNewIntent(Intent intent),而onCreate(Bundle savedInstanceState) 方法,将不再回调。

四:singleInstance 模式就比较强大一些,有意思一些。指定为singleInstance模式的活动会启动一个新的返回栈来管理活动。那么这样做有什么意义呢?想象以下场景,假设我们的程序中有一个活动是允许其他程序调用的,如果我们想实现其他程序和我们的程序可以共享这个活动的实例,应该如何实现呢?使用前面三种启动模式肯定是做不到的,因为每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈入栈是必然是创建了新的实例。而使用singleInstance 模式就可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个活动,不管是那个应用程序来访问这个活动,都公用同一个返回栈,也就解决了共享活动实例的问题。

五:TaskAffinity。
用法一:如果你给一个activity设置了singleInstance,如果不设置taskAffinity的话,taskAffinity默认与application是同一个(包名)。按下home键时系统会清理最近不活动的activity 和 application相同的taskAffinity所有处于后台的栈,所以需要给此活动页面设置taskAffinity,比如: android:taskAffinity=“.bmWebView5” ,这样此活动所在后台栈就不会被清理。
注意:android:taskAffinity=“.xxxxx” 需要打“.” 按下Home键在回到应用后,系统会优先加载显示系统默认栈的活动。

TaskAffinity 的相关知识点。(比较重要的一块知识点)

用法二:TaskAffinity 和 singleTask 配合使用(推荐)

当TaskAffinity和SingleTask启动模式配对使用时,待启动的Activity都会运行TaskAffinity名称相同的任务栈中。
说明:注意不需要所有的Activity都在清单文件中添加 android:launchMode=“singleTask” ,给首次启动的Activity添加即可,后面所有的只需要 taskAffinity 名称相同即可。

Android TaskAffinity和allowTaskReparenting属性

intent.setFlags方法中的参数值含义

一. intent.setFlags()方法中的参数值含义:
1.FLAG_ACTIVITY_CLEAR_TOP:例如现在的栈情况为:A B C D 。D此时通过intent跳转到B,如果这个intent添加FLAG_ACTIVITY_CLEAR_TOP标记,则栈情况变为:A B。如果没有添加这个标记,则栈情况将会变成:A B C D B。也就是说,如果添加了FLAG_ACTIVITY_CLEAR_TOP标记,并且目标Activity在栈中已经存在,则将会把位于该目标activity之上的activity从栈中弹出销毁。这跟上面把B的Launch mode设置成singleTask类似。简而言之,跳转到的activity若已在栈中存在,则将其上的activity都销掉。注意:虽与singleTask类似,但不同点为:如果目标Activity在栈中已经存在,仍然会再此执行Activity的生命周期。当然,onNewIntent(Intent intent) 方法也不会回调。

2.FLAG_ACTIVITY_NEW_TASK:例如现在栈1的情况是:A B C。C通过intent跳转到D,并且这个intent添加了FLAG_ACTIVITY_NEW_TASK标记,如果D这个Activity在Manifest.xml中的声明中添加了Task affinity,系统首先会查找有没有和D的Task affinity相同的task栈存在,如果有存在,将D压入那个栈,如果不存在则会新建一个D的affinity的栈将其压入。如果D的Task affinity默认没有设置,则会把其压入栈1,变成:A B C D,这样就和不加FLAG_ACTIVITY_NEW_TASK标记效果是一样的了。注意如果试图从非activity的非正常途径启动一个activity(例见下文“intent.setFlags()方法中参数的用例”),比如从一个service中启动一个activity,则intent比如要添加FLAG_ACTIVITY_NEW_TASK标记(编者按:activity要存在于activity的栈中,而非activity的途径启动activity时必然不存在一个activity的栈,所以要新起一个栈装入启动的activity)。简而言之,跳转到的activity根据情况,可能压在一个新建的栈中。

3.FLAG_ACTIVITY_NO_HISTORY:例如现在栈情况为:A B C。C通过intent跳转到D,这个intent添加FLAG_ACTIVITY_NO_HISTORY标志,则此时界面显示D的内容,但是它并不会压入栈中。如果按返回键,返回到C,栈的情况还是:A B C。如果此时D中又跳转到E,栈的情况变为:A B C E,此时按返回键会回到C,因为D根本就没有被压入栈中。简而言之,跳转到的activity不压在栈中。

4.FLAG_ACTIVITY_SINGLE_TOP:和Activity的Launch mode的singleTop类似。如果某个intent添加了这个标志,并且这个intent的目标activity就是栈顶的activity,那么将不会新建一个实例压入栈中。简而言之,目标activity已在栈顶则跳转过去,不在栈顶则在栈顶新建activity。

5.FLAG_ACTIVITY_REORDER_TO_FRONT: 如果给Intent对象设置了这个标记,那么将会导致任务历史堆栈中既存的Activity被带到前台。比如: 如果已经启动了四个Activity:A,B,C和D,在D Activity里,想再启动一个Actvity B,但不变成A,B,C,D,B,而是希望是A,C,D,B。 就可以使用这个属性。

二.intent.setFlags()方法中参数的用例:

很多人使用startActivity时候,会碰到如下的异常:
Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
都知道,Context中有一个startActivity方法,Activity继承自Context,重载了startActivity方法。如果使用Activity的startActivity方法,不会有任何限制,而如果使用Context的startActivity方法的话,就需要开启一个新的task(编者按:参见一.2.的编者按),遇到上面那个异常的,都是因为使用了Context的startActivity方法。解决办法是:Java代码中加一个flag,即intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)。这样就可以在新的task里面启动这个Activity了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
`intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)` 是用于设置 Intent 的标志,指示在启动活动时创建一个新的任务。 通过设置该标志,您可以在一个新的任务启动活动,而不是将其添加到当前任务的堆。这意味着新活动将在一个新的任务打开,并成为该任务的根活动。 这种情况通常发生在以下情况下: 1. 在非活动上下文启动活动:例如,在服务、广播接收器或应用程序的后台任务启动活动时,由于缺乏 UI 上下文,您需要设置 `FLAG_ACTIVITY_NEW_TASK` 标志来创建一个新的任务,以便启动活动。 2. 启动独立的任务:有时,您可能希望将某个活动作为一个单独的任务打开,而不是与当前应用程序的任务关联。通过设置 `FLAG_ACTIVITY_NEW_TASK` 标志,您可以实现这一点。 下面是一个示例代码片段,演示如何使用 `intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)` 启动一个新的任务: ```java Intent intent = new Intent(context, YourActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent); ``` 在此示例,我们创建了一个 Intent 对象,指定目标活动为 `YourActivity`。然后,我们使用 `setFlags()` 方法设置 `FLAG_ACTIVITY_NEW_TASK` 标志。最后,我们使用 `startActivity()` 方法启动活动。 请注意,使用 `FLAG_ACTIVITY_NEW_TASK` 标志启动活动时,您需要确保目标活动在 AndroidManifest.xml 文件被声明为具有 `android:launchMode="standard"` 或 `android:launchMode="singleTask"` 属性,以便正确处理任务和活动的创建和销毁。 如果您有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值