介绍

  启动模式简单地说就是Activity启动时的策略,在AndroidManifest.xml中的标签的android:launchMode属性设置;

  启动模式有4种,分别为standard、singleTop、singleTask、singleInstance;

讲解启动模式之前,有必要先讲解一下“任务栈”的概念;

任务栈

  每个应用都有一个任务栈,是用来存放Activity的,功能类似于函数调用的栈,先后顺序代表了Activity的出现顺序;比如Activity1–>Activity2–>Activity3,则任务栈为:

(1)standard:每次激活Activity时(startActivity),都创建Activity实例,并放入任务栈;

(2)singleTop:如果某个Activity自己激活自己,即任务栈栈顶就是该Activity,则不需要创建,其余情况都要创建Activity实例;

(3)singleTask:如果要激活的那个Activity在任务栈中存在该实例,则不需要创建,只需要把此Activity放入栈顶,并把该Activity以上的Activity实例都pop;

(4)singleInstance:如果应用1的任务栈中创建了MainActivity实例,如果应用2也要激活MainActivity,则不需要创建,两应用共享该Activity实例;

介绍

1. standard

默认启动模式,每次激活Activity时都会创建Activity,并放入任务栈中。

2. singleTop

接下来就是singleTop模式。它的表现几乎和standard模式一模一样,一个singleTop Activity 的实例可以无限多,唯一的区别是如果在栈顶已经有一个相同类型的Activity实例,Intent不会再创建一个Activity,而是通过onNewIntent()被发送到现有的Activity。

在singleTop模式下我们需要同时在onCreate() 和 onNewIntent()中处理发来的intent,以满足不同情况。

3. singleTask

这种模式和standard以及singleTop有很大不同。singleTask模式的Activity只允许在系统中有一个实例。如果系统中已经有了一个实例,持有这个实例的任务将移动到顶部,同时intent将被通过onNewIntent()发送。如果没有,则会创建一个新的Activity并置放在合适的任务中。

4. singleInstance

在一个新栈中创建该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦该模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果相当于多个应用程序共享一个应用,不管谁激活该Activity都会进入同一个应用中。

应用

SingTask的应用:

可以用来退出整个应用。

将主Activity设为SingTask模式,然后在要退出的Activity中转到主Activity,然后重写主Activity的onNewIntent函数,并在函数中加上一句finish

singleTop的应用:

这种启动模式的用例之一就是搜索功能。假设我们创建了一个搜索框,点击搜索的时候将导航到一个显示搜索结果列表的SearchActivity中,为了更好的用户体验,这个搜索框一般也会被放到SearchActivity中,这样用户想要再次搜索就不需要按返回键。

想像一下,如果每次显示搜索结果的时候我们都启动一个新的activity,10次搜索10个activity,那样当我们想返回最初的那个activity的时候需要按10次返回。

所以我们应该这样,如果栈顶已经有一个SearchActivity,我们将Intent发送给现有的activity,让它来更新搜索结果。这样就只会有一个在栈顶的SearchActivity,只需点一次back就可以回到之前的activity。

singleInstance的应用:

代码如例

<activity
    android:name="com.itheima.taskstack.MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity>
<activity android:name="com.itheima.taskstack.SecondActivity"android:launchMode="singleInstance "></activity>

运行程序,此时任务栈创建,并将MainActivity即01入栈,效果如图1-13所示:

点击“开启界面02“按钮,打开SecondActivity即02入栈;然后点击”开启界面01“按钮即01再次入栈;点击“Back”此时01出栈;再次点击“Back”此时01再次出栈,此时01所在的任务栈清空但02所在的任务栈仍存在。这一过程变化如下图1-4所示:

从图1-4可知:在点击“开启界面02”时,由于SecondActivity的启动模式为“singleInstance”,这种启动模式非常特殊,此时02会入栈到自己的任务栈中,02和01分别在不同的任务栈中;再次点击“开启界面01”按钮,则01再次入栈;点击“Back”则01出栈,再次点击“Back”则01再次出栈,此时01所在的任务栈清空,但02所在的任务栈仍存在。

要想防止在任务管理器的时候无法看到另外一个Activity,只要为singleInstance Activity设置taskAffinity属性就可以了。

<activity
            android:name=".SingleInstanceActivity"android:label="singleInstance launchMode"android:launchMode="singleInstance"android:taskAffinity="">

onNewIntent

onNewIntent()非常好用,Activity第一启动的时候执行onCreate()—->onStart()—->onResume()等后续生命周期函数,也就时说第一次启动Activity并不会执行到onNewIntent(). 而后面如果再有想启动Activity的时候,那就是执行onNewIntent()—->onResart()——>onStart()—–>onResume(). 如果android系统由于内存不足把已存在Activity释放掉了,那么再次调用的时候会重新启动Activity即执行onCreate()—->onStart()—->onResume()等。

当调用到 (intent)的时候,需要在onNewIntent() 中使用setIntent(intent)赋值给Activity的Intent.否则,后续的getIntent()都是得到老的Intent。

如果IntentActivity处于任务栈的顶端,也就是说之前打开过的Activity,现在处于

I/@@@philn(12410): onPause
I/@@@philn(12410): onStop 状态的话

其他应用再发送Intent的话,执行顺序为:

I/@@@philn(12410): onNewIntent
I/@@@philn(12410): onRestart
I/@@@philn(12410): onStart
I/@@@philn(12410): onResume

在Android应用程序开发的时候,从一个Activity启动另一个Activity并传递一些数据到新的Activity上非常简单,但是当您需要让后台运行的Activity回到前台并传递一些数据可能就会存在一点点小问题。

首先,在默认情况下,当您通过Intent启到一个Activity的时候,就算已经存在一个相同的正在运行的Activity,系统都会创建一个新的Activity实例并显示出来。为了不让Activity实例化多次,我们需要通过在AndroidManifest.xml配置activity的加载方式(launchMode)以实现单任务模式,如下所示:

<activity android:label="@string/app_name" android:launchmode="singleTask"android:name="Activity1"></activity>

如果使用的是singleTop, onNewIntent也是会执行到的

launchMode为singleTask的时候,通过Intent启到一个Activity,如果系统已经存在一个实例,系统就会将请求发送到这个实例上,但这个时候,系统就不会再调用通常情况下我们处理请求数据的onCreate方法,而是调用onNewIntent方法,如下所示:

 protected void onNewIntent(Intent intent) {super.onNewIntent(intent);setIntent(intent);//must store the new intent unless getIntent() will return the old oneprocessExtraData();}

不要忘记,系统可能会随时杀掉后台运行的Activity,如果这一切发生,那么系统就会调用onCreate方法,而不调用onNewIntent方法,一个好的解决方法就是在onCreate和onNewIntent方法中调用同一个处理数据的方法,如下所示:

public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);processExtraData();}protected void onNewIntent(Intent intent) {super.onNewIntent(intent);setIntent(intent);//must store the new intent unless getIntent() will return the old oneprocessExtraData()}private void processExtraData(){Intent intent = getIntent();//use the data received here}

总结

在SDK中关于Task(guide/topics/fundamentals.html#acttask),有一个很好的比方,说,Task就相当于应用(application)的概念。在开发人员眼中,开发一个Android程序,是做一个个独门独户的组件,但对于一般用户而言,它们感知到的,只是一个运行起来的整体应用,这个整体背后,就是Task。
Task,简单的说,就是一组以栈的模式聚集在一起的Activity组件集合。它们有潜在的前后驱关联,新加入的Activity组件,位于栈顶,并仅有在栈顶的Activity,才会有机会与用户进行交互。而当栈顶的Activity完成使命退出的时候,Task会将其退栈,并让下一个将跑到栈顶的Activity来于用户面对面,直至栈中再无更多Activity,Task结束。

事件 Task栈(粗体为栈顶组件)
点开Email应用,进入收件箱(Activity A) A
选中一封邮件,点击查看详情(Activity B) AB
点击回复,开始写新邮件(Activity C) ABC
写了几行字,点击选择联系人,进入选择联系人界面(Activity D) ABCD
选择好了联系人,继续写邮件 ABC
写好邮件,发送完成,回到原始邮件 AB
点击返回,回到收件箱 A
退出Email程序 null

如上表所示,是一个实例。

用户从进入邮箱开始,到回复完成,退出应用整个过程的Task栈变化。这是一个标准的栈模式,对于大部分的状况,这样的Task模型,足以应付,但是,涉及到实际的性能、开销等问题,就会变得残酷许多。比如,启动一个浏览器,在Android中是一个比较沉重的过程,它需要做很多初始化的工作,并且会有不小的内存开销。但与此同时,用浏览器打开一些内容,又是一般应用都会有的一个需求。设想一下,如果同时有十个运行着的应用(就会对应着是多个Task),都需要启动浏览器,这将是一个多么残酷的场面,十个Task栈都堆积着很雷同的浏览器Activity,是多么华丽的一种浪费啊。于是你会有这样一种设想,浏览器Activity,可不可以作为一个单独的Task而存在,不管是来自那个Task的请求,浏览器的Task,都不会归并过去。这样,虽然浏览器Activity本身需要维系的状态更多了,但整体的开销将大大的减少,这种舍小家为大家的行为,还是很值得歌颂的。

如此值得歌颂的行为,Android当然会举双手支持的。在Android中,每一个Activity的Task模式,都是可以由Activity提供方(通过配置文件…)和Activity使用方(通过Intent中的flag信息…)进行配置和选择。当然,使用方对Activity的控制力,是限定在提供方允许的范畴内进行,提供方明令禁止的模式,使用方是不能够越界使用的。

在SDK中(guide/topics/fundamentals.html#acttask),将两者实现Task模式配置的方式,写的非常清晰了,我再很絮叨挑选一些来解释一下(完整可配置项,一定要看SDK,下面只是其中常用的若干项…)。提供方对组件的配置,是通过配置文件(Manifest)项来进行的,而调用方,则是通过Intent对象的flag进行抉择的。相对于标准的Task栈的模式,配置的主要方向有两个:一则是破坏已有栈的进出规则,或样式;另一则是开辟新Task栈完成本应在同一Task栈中完成的任务。

对于应用开发人员而言,中的launchMode属性,是需要经常打交道的。它有四种模式:”standard”, “singleTop”, “singleTask”, “singleInstance”。

standard模式, 是默认的也是标准的Task模式,在没有其他因素的影响下,使用此模式的Activity,会构造一个Activity的实例,加入到调用者的Task栈中去,对于使用频度一般开销一般什么都一般的Activity而言,standard模式无疑是最合适的,因为它逻辑简单条理清晰,所以是默认的选择。

而singleTop模式,基本上于standard一致,仅在请求的Activity正好位于栈顶时,有所区别。此时,配置成singleTop的Activity,不再会构造新的实例加入到Task栈中,而是将新来的Intent发送到栈顶Activity中,栈顶的Activity可以通过重载onNewIntent来处理新的Intent(当然,也可以无视…)。这个模式,降低了位于栈顶时的一些重复开销,更避免了一些奇异的行为(想象一下,如果在栈顶连续几个都是同样的Activity,再一级级退出的时候,这是怎么样的用户体验…),很适合一些会有更新的列表Activity展示。一个活生生的实例是,在Android默认提供的应用中,浏览器(Browser)的书签Activity(BrowserBookmarkPage),就用的是singleTop。

singleTop模式,虽然破坏了原有栈的逻辑(复用了栈顶,而没有构造新元素进栈…),但并未开辟专属的Task。而singleTask,和singleInstance,则都采取的另辟Task的蹊径。标志为singleTask的Activity,最多仅有一个实例存在,并且,位于以它为根的Task中。所有对该Activity的请求,都会跳到该Activity的Task中展开进行。singleTask,很象概念中的单件模式,所有的修改都是基于一个实例,这通常用在构造成本很大,但切换成本较小的Activity中。在Android源码提供的应用中,该模式被广泛的采用,最典型的例子,还是浏览器应用的主Activity(名为Browser…),它是展示当前tab,当前页面内容的窗口。它的构造成本大,但页面的切换还是较快的,于singleTask相配,还是挺天作之合的。

相比之下,singleInstance显得更为极端一些。在大部分时候singleInstance与singleTask完全一致,唯一的不同在于,singleInstance的Activity,是它所在栈中仅有的一个Activity,如果涉及到的其他Activity,都移交到其他Task中进行。这使得singleInstance的Activity,像一座孤岛,彻底的黑盒,它不关注请求来自何方,也不计较后续由谁执行。在Android默认的各个应用中,很少有这样的Activity,在我个人的工程实践中,曾尝试在有道词典的快速取词Activity中采用过,是因为我觉得快速取词入口足够方便(从notification中点选进入),并且会在各个场合使用,应该做得完全独立。

除了launchMode可以用来调配Task,的另一属性taskAffinity,也是常常被使用。taskAffinity,是一种物以类聚的思想,它倾向于将taskAffinity属性相同的Activity,扔进同一个Task中。不过,它的约束力,较之launchMode而言,弱了许多。只有当中的allowTaskReparen ting设置为true,抑或是调用方将Intent的flag添加FLAG_ACTIVITY_NEW_TASK属性时才会生效。如果有机会用到Android的Notification机制就能够知道,每一个由notification进行触发的Activity,都必须是一个设成FLAG_ACTIVITY_NEW_TASK的Intent来调用。这时候,开发者很可能需要妥善配置taskAffinity属性,使得调用起来的Activity,能够找到组织,在同一taskAffinity的Task中进行运行。

参考

  • 深入Android 【五】 —— 任务和进程

  • Android入门:Activity四种启动模式

  • onNewIntent调用时机

  • Activity的四种启动模式和onNewIntent()

  • Activity启动模式图文详解:standard, singleTop, singleTask 以及 singleInstance

  • [Android] 138. singleTask和singleInstance启动模式

Activity之四大启动模式相关推荐

  1. Activity中四大启动模式

    在AndroidManifest.xml中 ,有一个默认的activity 在它里面可以设置activity启动模式, android:launchMode=" " ,该属性用于配 ...

  2. android 怎么自定义任务栈,Android中的Activity详解--启动模式与任务栈

    目录 Activity 生命周期 任务栈 启动模式 Intent Flag taskAffinity属性 1.Activity activity的简单介绍就不写了,作为最常用的四大组件之一,肯定都很熟 ...

  3. Activity中AndroidMainfest启动模式

    Activity中AndroidMainfest启动模式 Android开发者在AndroidMainifest文件中一共设计了四种启动模式:standard,singleTop,singleTask ...

  4. Activity四种启动模式详细整理

    Activity四种启动模式详细整理 1.Standard standard模式,顾名思议就是标准启动模式,默认启动模式. 一个Activity如果不知道它的启动模式,那么它就是按Standard模式 ...

  5. android的四种启动模式,(转)彻底弄懂Activity四大启动模式

    原地址:https://blog..net/mynameishuangshuai/article/details/51491074 最近有几位朋友给我留言,让我谈一下对Activity启动模式的理解. ...

  6. Android入门:Activity四种启动模式

    2019独角兽企业重金招聘Python工程师标准>>> 一.启动模式介绍 启动模式简单地说就是Activity启动时的策略,在Android Manifest.xml中的标签的and ...

  7. Android Activity Launch Mode 启动模式详解

    简介 android:launchMode 属性能设置 Activity 对象启动时是否使用已有的实例还是多次创建,会使得交互设计更加良好,也能避免很多问题. 它是 Androidmanifest.x ...

  8. Activity的launchMode启动模式 day7

    2019独角兽企业重金招聘Python工程师标准>>> Activity的launchMode day7 在功能清单AndroidManifest.xml 里 设置 启动模式 如: ...

  9. Android入门之Activity四种启动模式

    一.启动模式介绍 启动模式简单地说就是Activity启动时的策略,在AndroidManifest.xml中的<Activity>标签的android:launchMode属性设置: 启 ...

最新文章

  1. react组件回顶部
  2. Python filter() 函数
  3. dedecms首页如何调用专题页描述和链接
  4. CLR运行时细节 - 继承多态的实现
  5. Link-Cut Tree
  6. solr mysql增量导入_急急急,在线等!solr4.10结合oracle增量导入数据问题!
  7. FTP 编程 5 文件传输与目录切换
  8. paip.批处理清理java项目冗余jar的方法
  9. awk内置字符串函数详解
  10. mysql从库数据源_SoapUI Pro教程:如何使用MySQL服务器作为数据源-从MySQL数据库获取数据...
  11. Objective-C语法之集合对象的那些事儿(九)
  12. python 递归函数例子
  13. 线性回归、bagging回归、随机森林回归
  14. springboot网上投资借贷中介服务毕业设计-附源码221506
  15. 2021年危险化学品经营单位安全管理人员最新解析及危险化学品经营单位安全管理人员模拟试题
  16. 小程序轮播图 swiper当前滑块容器样式
  17. 17python实操案例五
  18. Cauchy distribution
  19. python读写、导入导出数据操作(简)
  20. Win10深度学习环境配置(CUDA+cuDNN+TensorFlow-gpu+Keras)

热门文章

  1. STM32CubeMX学习笔记(49)——USB接口使用(MSC基于SD卡模拟U盘)
  2. 渗透测试技术----被动信息收集(一)--nslookup、dig、DNS字典爆破、whois
  3. ASP.NET CodeBehind
  4. fcn网络结构代码_经典网络复现系列(一):FCN
  5. Storm 核心概念详解
  6. KubeVela 1.4.x 官方文档
  7. python实现电子相册_qt电子相册
  8. Kruskal 算法与 Prim 算法
  9. 计算机为什么逻辑判断准确,一道没有正确答案的「逻辑判断-最强程度」题
  10. 1000个常用建模材质,提高效率