android基础总结篇之二:Activity的四种launchMode
我们今天要讲的是activity的四种launchmode。
launchmode在多个activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的activity实例,是否重用已存在的activity实例,是否和其他activity实例公用一个task里。这里简单介绍一下task的概念,task是一个具有栈结构的对象,一个task可以管理多个activity,启动一个应用,也就创建一个与之对应的task。
activity一共有以下四种launchmode:
1.standard
2.singletop
3.singletask
4.singleinstance
我们可以在androidmanifest.xml配置<activity>的android:launchmode属性为以上四种之一即可。
下面我们结合实例一一介绍这四种lanchmode:
1.standard
standard模式是默认的启动模式,不用为<activity>配置android:launchmode属性即可,当然也可以指定值为standard。
我们将会一个activity,命名为firstactivity,来演示一下标准的启动模式。firstactivity代码如下:
package com.scott.launchmode; import android.app.activity; import android.content.intent; import android.os.bundle; import android.view.view; import android.widget.button; import android.widget.textview; public class firstactivity extends activity { @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.first); textview textview = (textview) findviewbyid(r.id.textview); textview.settext(this.tostring()); button button = (button) findviewbyid(r.id.button); button.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent = new intent(firstactivity.this, firstactivity.class); startactivity(intent); } }); } }
我们firstactivity界面中的textview用于显示当前activity实例的序列号,button用于跳转到下一个firstactivity界面。
然后我们连续点击几次按钮,将会出现下面的现象:
我们注意到都是firstactivity的实例,但序列号不同,并且我们需要连续按后退键两次,才能回到第一个fristactivity。standard模式的原理如下图所示:
如图所示,每次跳转系统都会在task中生成一个新的firstactivity实例,并且放于栈结构的顶部,当我们按下后退键时,才能看到原来的firstactivity实例。
这就是standard启动模式,不管有没有已存在的实例,都生成新的实例。
2.singletop
我们在上面的基础上为<activity>指定属性android:launchmode="singletop",系统就会按照singletop启动模式处理跳转行为。我们重复上面几个动作,将会出现下面的现象:
我们看到这个结果跟standard有所不同,三个序列号是相同的,也就是说使用的都是同一个firstactivity实例;如果按一下后退键,程序立即退出,说明当前栈结构中只有一个activity实例。singletop模式的原理如下图所示:
正如上图所示,跳转时系统会先在栈结构中寻找是否有一个firstactivity实例正位于栈顶,如果有则不再生成新的,而是直接使用。也许朋友们会有疑问,我只看到栈内只有一个activity,如果是多个activity怎么办,如果不是在栈顶会如何?我们接下来再通过一个示例来证实一下大家的疑问。
我们再新建一个activity命名为secondactivity,如下:
package com.scott.launchmode; import android.app.activity; import android.content.intent; import android.os.bundle; import android.view.view; import android.widget.button; import android.widget.textview; public class secondactivity extends activity { @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.second); textview textview = (textview) findviewbyid(r.id.textview); textview.settext(this.tostring()); button button = (button) findviewbyid(r.id.button); button.setonclicklistener(new view.onclicklistener() { @override public void onclick(view v) { intent intent = new intent(secondactivity.this, firstactivity.class); startactivity(intent); } }); } }
然后将之前的firstactivity跳转代码改为:
intent intent = new intent(firstactivity.this, secondactivity.class); startactivity(intent);
是的,firstactivity会跳转到secondactivity,secondactivity又会跳转到firstactivity。演示结果如下:
我们看到,两个firstactivity的序列号是不同的,证明从secondactivity跳转到firstactivity时生成了新的firstactivity实例。原理图如下:
我们看到,当从secondactivity跳转到firstactivity时,系统发现存在有firstactivity实例,但不是位于栈顶,于是重新生成一个实例。
这就是singletop启动模式,如果发现有对应的activity实例正位于栈顶,则重复利用,不再生成新的实例。
3.singletask
在上面的基础上我们修改firstactivity的属性android:launchmode="singletask"。演示的结果如下:
我们注意到,在上面的过程中,firstactivity的序列号是不变的,secondactivity的序列号却不是唯一的,说明从secondactivity跳转到firstactivity时,没有生成新的实例,但是从firstactivity跳转到secondactivity时生成了新的实例。singletask模式的原理图如下图所示:
在图中的下半部分是secondactivity跳转到firstactivity后的栈结构变化的结果,我们注意到,secondactivity消失了,没错,在这个跳转过程中系统发现有存在的firstactivity实例,于是不再生成新的实例,而是将firstactivity之上的activity实例统统出栈,将firstactivity变为栈顶对象,显示到幕前。也许朋友们有疑问,如果将secondactivity也设置为singletask模式,那么secondactivity实例是不是可以唯一呢?在我们这个示例中是不可能的,因为每次从secondactivity跳转到firstactivity时,secondactivity实例都*出栈,下次等firstactivity跳转到secondactivity时,找不到存在的secondactivity实例,于是必须生成新的实例。但是如果我们有thirdactivity,让secondactivity和thirdactivity互相跳转,那么secondactivity实例就可以保证唯一。
这就是singletask模式,如果发现有对应的activity实例,则使此activity实例之上的其他activity实例统统出栈,使此activity实例成为栈顶对象,显示到幕前。
4.singleinstance
这种启动模式比较特殊,因为它会启用一个新的栈结构,将acitvity放置于这个新的栈结构中,并保证不再有其他activity实例进入。
我们修改firstactivity的launchmode="standard",secondactivity的launchmode="singleinstance",由于涉及到了多个栈结构,我们需要在每个activity中显示当前栈结构的id,所以我们为每个activity添加如下代码:
textview taskidview = (textview) findviewbyid(r.id.taskidview); taskidview.settext("current task id: " + this.gettaskid());
然后我们再演示一下这个流程:
我们发现这两个activity实例分别被放置在不同的栈结构中,关于singleinstance的原理图如下:
我们看到从firstactivity跳转到secondactivity时,重新启用了一个新的栈结构,来放置secondactivity实例,然后按下后退键,再次回到原始栈结构;图中下半部分显示的在secondactivity中再次跳转到firstactivity,这个时候系统会在原始栈结构中生成一个firstactivity实例,然后回退两次,注意,并没有退出,而是回到了secondactivity,为什么呢?是因为从secondactivity跳转到firstactivity的时候,我们的起点变成了secondactivity实例所在的栈结构,这样一来,我们需要“回归”到这个栈结构。
如果我们修改firstactivity的launchmode值为singletop、singletask、singleinstance中的任意一个,流程将会如图所示:
singleinstance启动模式可能是最复杂的一种模式,为了帮助大家理解,我举一个例子,假如我们有一个share应用,其中的shareactivity是入口activity,也是可供其他应用调用的activity,我们把这个activity的启动模式设置为singleinstance,然后在其他应用中调用。我们编辑shareactivity的配置:
<activity android:name=".shareactivity" android:launchmode="singleinstance"> <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.single_instance_share" /> <category android:name="android.intent.category.default" /> </intent-filter> </activity>
然后我们在其他应用中这样启动该activity:
intent intent = new intent("android.intent.action.single_instance_share"); startactivity(intent);
当我们打开shareactivity后再按后退键回到原来界面时,shareactivity做为一个独立的个体存在,如果这时我们打开share应用,无需创建新的shareactivity实例即可看到结果,因为系统会自动查找,存在则直接利用。大家可以在shareactivity中打印一下taskid,看看效果。关于这个过程,原理图如下:
原文链接:http://blog.csdn.net/liuhe688/article/details/6754323
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 详解Android首选项框架的使用实例
下一篇: java中设计模式(多例)的实例详解