安卓Activity启动模式

最近一直在看任务还有Activity 启动模式这块,一直对这块存在疑惑,为什么要有不同的启动模式?使用这些会为我们的开发带来什么好处?今天周讨论,和同事们针对此问题,大家相互探讨了一下。
在多Activity 开发中,有可能是自己应用之间的Activity 跳转,或者夹带其他应用的可复用Activity 。也可能会希望跳转到原来某个Activity 实例,而不是产生大量重复的Activity 。为了有效的利用有限的内存资源,这需要为Activity 配置特定的加载模式,而不是使用默认的加载模式。
加载模式分类及在哪里配置
Activity 有四种加载模式:

  • standard
  • singleTop
  • singleTask
  • singleInstance
设置的位置在AndroidManifest.xml文件中activity元素的android:launchMode属性:
<activity android:name=".Activity2" android:launchMode="singleTask"></activity>
也可以在Eclipse ADT中图形界面中编辑:

针对四种启动模式,我做了一个小例子——LaunchMode_Test,大家可以通过按照下面的操作修改例子启动模式,来加深理解。三个Activity界面如下
Fx_Main:
Activity2:
file:///E:/Users/hyj/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpgfile:///E:/Users/hyj/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg
Activity3:
file:///E:/Users/hyj/AppData/Local/Temp/msohtmlclip1/01/clip_image008.jpg
standard
首先说standard模式,也就是默认模式,不需要配置launchMode。运行例子从Fx_Main---->Activity2---->Activity2---->Activity2可见,一直点回到Activity2按钮时,Log信息如下:
file:///E:/Users/hyj/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg
发现每次都创建了Activity2的新实例。standard的加载模式就是这样的,intent将发送给新的Activity实例。
现在点Android设备的回退键,可以看到是按照刚才创建Activity实例的倒序依次出现,类似退栈的操作,而刚才操作跳转按钮的过程是压栈的操作。
singleTop
singleTop 和standard模式,都会将intent发送新的实例(后两种模式不发送到新的实例,如果已经有了的话)。不 过,singleTop要求如果创建intent的时候栈顶已经有要创建的Activity的实例,则将intent发送给该实例,而不发送给新的实例。
还是用刚才的示例,只需将Activity2的launchMode改为singleTop,就能看到区别。
运行的时候会发现,按多少遍按钮,都是相同的Activity2实例,因为该实例在栈顶,因此不会创建新的实例。如果回退,回到Fx_Main,然后将退出应用。
file:///E:/Users/hyj/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg
singleTop 模式,可用来解决栈顶多个重复相同的Activity的问题。
如果是Fx_Main跳转到Activity2,再跳转到Fx_Main,行为就和standard一样了,会在Activity2跳转到Fx_Main的时候创建Fx_Main的新实例,因为当时的栈顶不是Activity2实例。
file:///E:/Users/hyj/AppData/Local/Temp/msohtmlclip1/01/clip_image014.jpg
singleTask
singleTask 模式和后面的singleInstance模式都是只创建一个实例的
当intent到来,需要创建singleTask模式Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。(注意此时原在此Activity栈中上面的Activity将会被杀死)。
把Activity2的启动模式改成singleTask,然后启动Fx_Main--->跳转到Activity2---->Activity3---->Actvity2此时看Log信息。
file:///E:/Users/hyj/AppData/Local/Temp/msohtmlclip1/01/clip_image016.jpg
可见从Ac3再跳转到Ac2时,因为Ac2之前在栈中是存在的所以不生成新的Ac2实例,而是在栈中找到此Ac2,并将在Ac2上面的Ac3杀死,所以此时栈中只有Fx_Main和Ac2,在Ac2点返回会直接退到Fx_Main然后退出。
singleInstance
解释singleInstance模式比较麻烦。
首先要说一下Task(任务)的概念。按照字面意思,任务就是自己要实现的一个目的,而在Android中的Task的定义是一系列Activity的集合,即要达到自己最终要到的Actvity,之前所有经历过的Actvity的集合。它可以是同一个应用内部的,也可以是两个不同应用的。Task可以认为是一个栈,可放入多个Activity。比如启动一个应用,那么 Android就创建了一个Task,然后启动这个应用的入口Activity,就是intent-filter中配置为main和launch的那个。这个Activity是根(Root)Activity,可能会在它的界面调用其他Activity,这些Activity如果按照上面那三个模式,也会在这个栈(Task)中,只是实例化的策略不同而已。
验证的办法是调用和打印Activity的taskId通过this.getTaskId();
会发现,无论切换Activity,taskId是相同的。
当然也可以在这个单一的Task栈中,放入别人的Activity,比如google地图,这样用户看过地图按回退键的时候,会退栈回到调用地图的Activity。对用户来说,并不觉得在操作多个应用。这就是Task的作用。可以理解为回退的作用是在先从当前Actvity同一个Task进行回退。
但是,有这样的需求,多个Task共享一个Activity(singleTask是在一个task中共享一个Activity)。
现成的例子是google地图。比如我有一个应用是导游方面的,其中调用的google地图Activity。那么现在我比如按home键,然后到应用列表中打开google地图,你会发现显示的就是刚才的地图,实际上是同一个Activity。
如果使用上面三种模式,是无法实现这个需求的。google地图应用中有多个上下文Activity,比如路线查询等的,导游应用也有一些上下文Activity。在各自应用中回退要回退到各自的上下文Activity中。
singleInstance 模式解决了这个问题(绕了这么半天才说到正题)。让这个模式下的Activity单独在一个task栈中。这个栈只有一个Activity。导游应用和google地图应用发送的intent都由这个Activity接收和展示。
这里又有两个问题:

  • 如果是这种情况,多个task栈也可以看作一个应用。比如导游应用启动地图Activity,实际上是在导游应用task栈之上 singleInstance模式创建的(如果还没有的话,如果有就是直接显示它)一个新栈,当这个栈里面的唯一Activity,地图Activity 回退的时候,只是把这个栈移开了,这样就看到导游应用刚才的Activity了;
  • 多个应用(Task)共享一个Activity要求这些应用都没有退出,比如刚才强调要用home键从导游应用切换到地图应用。因为,如果退出导游应用,而这时也地图应用并未运行的话,那个单独的地图Activity(task)也会退出了。
然后进行测试,我们还是将Activity2的启动模式设置为singleInstance模式,然后启动Fx_Main---->Actvity2---->Actvity3然后看一下Log信息。
file:///E:/Users/hyj/AppData/Local/Temp/msohtmlclip1/01/clip_image018.jpg
可以看到Fx_Main以及Activity3的TaskID为9,而Actvity2的TaskID为10,此时在Actvity3点返回会发现先退到Fx_Main,继续返回会到Actvity2最后退出。
遗留问题:
1.
IntentFilter 里设置优先级无效,系统仍然会弹出activity 选择列表。
解答:虽然优先级定义是-1000~1000 ,但只有当存在与负数比较时,优先级就会发生作用,即正数之间比较,以及正数与0 之间比较都不会出现优先级高低问题,但是正数与负数,0 与负数,或者负数之间进行比较,优先级就会发挥作用,而且越大的优先级越高。
2.
如何显式调用不同应用之间的activity
未解决
3.
按照SDK 中的说明使用 singTask 启动模式系统会在新 task 根部创建一个 activity 并且将 intent 指向它 。然而,如果这个activity 对象已经存在,系统通过调用onNewIntent() intent 指向这个已经存在的activity 对象,而不是创建一个新的activity
通过举例验证,如果activity 已经存在,且设置为singTask 模式,是不会再创建新的activity 实例的。
但是红色部分说在新task 根据创建一个activity 一直未解决
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值