您的位置:首页 > 移动开发 > Android开发

Android四大组件---Activity之启动模式及启动模式的应用场景

2016-01-11 20:39 441 查看
在“Android性能优化”中有这么一条规则:
复用、回收Activity对象:


临时的activity及时finish,

[b][b]主界面Activity启动模式设置singleTask,一般界面Activity的启动模式设置为[/b][/b]

[b][b][b][b]singleTop。[/b][/b][/b][/b]
那么这条“性能优化的规则”到底是为什么这么规定呢?OK,本篇博文将为大家解开这个迷惑。

在介绍Activity的启动模式之前我先介绍一下“回退栈”。

(一)、任务Task:

1、概念:

一个任务(task)就是在执行某项工作时与用户进行交互的Activity的集合。这些Activity按照被打开的顺序依次被安排在一个堆栈中(回退栈)。

2、主屏页面:

设备的主屏是大多数任务的启动位置,当用户触摸一个应用程序启动器图标(或者app快捷图标),应用程序的任务就会在前台显示。如果相关应用程序的任务不存在,那么就会有一个新的任务被创建,并且应用程序打开的“主”Activity会作为任务中的根Activity。
(二)、回退栈:
1、概念:
在当前的Activity启动了另一个Activity时,这个新的Activity被放到了堆栈的顶部,并且带有焦点。前一个Activity并没有消失,而是保存在回退栈中,此时它处于停止状态。
当用户按下回退按钮时,当前的Activity会被从回退栈的顶部弹出(这个Activity被销毁),而前一个Activity被恢复。堆栈中的Activity不会被重新排列。因此,回退栈的操作跟后进先出的对象结构是一样的。
在用户按下回退按钮时,当前Activity被销毁,并且前一个Activity被恢复。如果用户继续按回退按钮,那么回退栈中的每个Activity会被依次弹出,前一个Activity会被显示,直到用户返回主屏(或者返回到任务开始时运行的那个Activity)。当所有的Activity从回退栈中被删除时,这个任务就不再存在了。



图1:用一个时间表显示了当前回退堆栈中的Activity之间在每个时间点的处理过程

2、多个任务:



图2.
两个任务:任务B在前台接受用户交互,而任务A则在后台等待被恢复


【注意】后台中可以同时拥有多个任务,但是如果用户同时运行了很多后台任务,系统为了回收内存可能销毁一些后台的Activity,从而导致Activity的状态丢失。
因为回退堆栈中的Activity不曾被重新排列,因此如果允许用户从多个Activity中启动一个特殊Activity,那么就会创建一个新的Activity实例,并且在堆栈的顶部弹出(而不是把之前的Activity实例带到堆栈的顶端)。这样在你的应用程序中一个Activity就可能被实例化多次(甚至来自不同任务)。

(三)、Activity和Task的默认行为的总结:
1、当Activity A启动Activity B时,ActivityA被终止,但是系统保留了它的状态(如滚动条的位置和录入表单的文本)。如果用户在Activity B中按回退按钮,Activity A会使用被保存的状态来进行恢复。
2、当用户通过按主页(Home)按钮离开一个任务时,当前的Activity会被终止,并且被放入后台。系统会保留任务中每个Activity的状态。如果用户随后通过选择启动图标来恢复这个任务,那么任务会来到前台,并且恢复了堆栈顶部的Activity。
3、如果用户按下回退按钮,当前的Activity会从堆栈中被弹出并且被销毁。堆栈中的前一个Activity会被恢复。Activity被销毁时,系统不会保留Activity的状态。
4、Activity能够被实例化多次,甚至来自其他任务。


[b]Activity的启动模式:[/b]
Activity有4种启动方式,分别是:

[b][b]①
[/b] standard

[b]②[/b] singleTop

[b]③[/b] singleTask

[b]④ [/b]singleInstance

可以根据实际的需求为Activity设置对应的启动模式,从而可以避免创建大量重复的Activity(造成占用手机内存)等问题。

[/b]
设置Activity的启动模式,只需要在AndroidManifest.xml里对应的<activity>标签设置[b]android:launchMode属性,如下

[/b]
<activity
android:name="com.lzy.androidstoragedemo.activity.HomeActivity"
<span style="background-color: rgb(255, 255, 51);">android:launchMode="singleTask"</span>
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.lzy.androidstoragedemo.activity.DownTimeActivity"
<span style="background-color: rgb(255, 255, 51);">android:launchMode="singleTop" </span>>
</activity>


下面就这四种模式做下总结性介绍:

standard(系统默认的启动方式):

这种启动模式是Activity的“标准启动模式”,也是Activity的默认启动模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加,因此一般情况下我们不采用这样的启动方式,这样不但重建Activity对象造成耗时,而且也会造成内存的浪费。

singleTop:[b][b][b]

[b] 如果在任务的栈顶正好存在该Activity的实例,就重用该实例,而不会创建新的Activity对象,不过它会调用onNewIntent()方法。如果栈顶部不存在就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。会回调onNewIntent()方法。

应用场景:从上面的介绍中,我们可以推断出[b][b][b][b][b][b]singleTop
[/b][/b][/b][/b][/b]启动模式适合于一些不常用的Activity页面,比如“找回密码”、“设置界面”等。

[/b][/b]
[/b][/b]singleTask:[/b]

如果在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,因此在它上面的实例将会被移除栈。如果栈中不存在该实例,将会创建新的实例放入栈中。

和singleTop在名字上即可看出区别,即singleTop每次只检测当前栈顶的Activity是否是我们需要请求创建的,而 singleTask则会检测栈中全部的Activity对象,从上向下,如果检测到是我们所请求的则会消灭此Activity对象上面的对象,直接把检
测到的我们需要的Activity置为栈顶。


应用场景:其在App内部适合作为程序入口点。从上面的介绍可以看出我们的App项目中调用较多的Activity页面使用于该启动模式,在项目中我们哪个Activity用的多?当然是首界面HomeActivity调用的较多,因此在首界面Activity的启动模式适用于改启动模式。当然其他利用较多的Activity也应该设置为该启动模式。

singleInstance:



与singleTask模式的区别是存放singleInstance模式窗口对象的回退栈不能有其他任何窗口对象。因此如果该窗口不存在,则要新建任务Task来存放该singleInstance模式窗口。也就是说getTaskId()会发现任务id发生了变化。

此启动模式和我们使用的浏览器工作原理类似,在多个程序中访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。此模式会节省大量的系统资源,因为他能保证要请求的Activity对象在当前的栈中只存在一个。
应用场景[b][b][b][b][b][b][b][b]singleInstance[/b][/b][/b]有一个重要的作用:作为外部App调用自己客户端程序的入口。比如说,使用微信调起自己的客户端某个页面,不做任何处理的情况下,按下回退或者当前Activity.finish(),页面不会停留在自己的客户端而是返回到微信的客户端页面。但是如果这个页面的启动模式设置为[b][b][b][b]singleTask,当按下返回键或者Activity。finish(),[/b][/b][/b][/b]页面都会停留在自己的客户端(因为自己的Application回退栈不为空),这明显不符合逻辑的。产品的要求是,回退必须回到微信客户端,而且要保证不杀死自己的Application.因此,显然其他的其他的启动模式都不具备这个功能。

OK,本篇博文到此结束,如有写的不准确地地方还请多多指点。

[/b][/b][/b][/b][/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: