Android开发Android知识移动开发

Android-Activity启动模式详解

2016-08-26  本文已影响265人  c37d344afd22

最近在写一个小Demo(然而现在也没写出来)。几天没更新,不知道有没有人还有一点点的小期待(估计没有)。让我边写文章边哭一会。。。


Activity的LaunchMode

为啥子需要启动模式?

我们知道启动Activity时会把Activity放入一个任务栈,所以当我们按back键时就会从Activity从任务栈里清除,当任务栈里为空时,系统就会回收这个任务栈。举个例子,我们在当前Activity启动当前的Activity,那么任务栈里就全是当前Activity,这样当然很二逼了!所以启动模式就出来了,目前有四种启动模式

standard

standard是标准模式,也就是默认模式。每次启动一个Activity就会创建一个新的实例,不管这个实例是否已经存在,这就是典型的多实例实现。一个任务栈可以有多个实例,每个实例也可以属于不同的任务栈,谁启动了这个Activity,这个Activity就运行在启动它的那个任务栈中,当我们用ApplicationContext去启动一个standard模式的Activity会报错,因为standard的Activity会进入启动他的Activity任务栈中,但是由于非Activity类型的Context并没有任务栈,所以这样就出问题了

singleTop

singleTop即栈顶复用模式,在这种模式下,如果新创建的Activity已经位于栈顶,那么就不会去创建新的实例,但是该Activity的onNewIntent会被调用,通过这个方法我们可以取出请求的信息。需要注意的是,该Activity的onCreate、onStart不会被调用,因为它没有发生改变。但是如果新的Activity不位于栈顶,那么就会创建一个新的实例。举个例子,比如现在一个任务栈有ABCD四个Activity,A位于栈底,D位于栈顶。这个时候如果去启动D,那么栈的情况还是ABCD四个实例,如果D的启动模式为standard,那么栈内就是ABCDD

singleTask

栈内复用模式,在这种模式情况下,只要Activity在一个栈中存在,那么启动这个Activity都不会重新创建实例,也会调用onNewIntent。当一个singleTask模式的Activity『A』被请求启动,首先系统会寻找是否有A所需的任务栈,如果不存在,那就重新创建一个任务栈,然后创建A的实例放入栈中。如果存在A所需的任务栈,这时再看A是否在这个栈中有实例存在,如果存在,那么久回把A调到栈顶并调用onNewIntent方法。如果不存在,那么就创建A的实例并且压入栈中,举个例子

singleInstance

单例模式,加强的singleTask,这种模式的Activity只能单独运行在一个单独的任务栈中,其他和singleTask一样

所需的任务栈?

在singleTask中提到『所需的任务栈』,什么是Activity所需的任务栈?这里就要提一个参数:TaskAffinity。这个参数标识了一个Activity所需的任务栈的名字,默认情况下所有的Activity所需的任务栈都是当前包名,当然我们也可以为每个Activity单独指定TaskAffinity,注意这个属性值必须不能和包名相同,TaskAffinity主要和singleTask配合使用,否则的话没什么意义。当启动一个被TaskAffinity标识了的Activity,那么该Activity就会运行在和TaskAffinity相同的任务栈中

我们用两种方式设置Activity的启动模式

  1. 在AndroidManifest里为Activity设置
    android:launchMode="singleTop/singleTask/singleInstance"
  2. 通过Intent设置标志位来指定
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

这两种方式第二种的优先级要高于第一种,也就是说两者同时存在时,以第二种为准


强行举个特殊的例子

如图:

首先我们看一下AndroidManifest里的配置

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity
    android:name=".SecondActivity"
    android:launchMode="singleTask"
    android:taskAffinity="com.task1" />

<activity
    android:name=".ThirdActivity"
    android:launchMode="singleTask"
    android:taskAffinity="com.task1" />

可以看到我们给SecondActivity和ThirdActivity设置了singleTask模式和taskAffinity,也就是所需的任务栈。从图里我们可以看出,首先由MainActivity启动SecondActivity,然后由SecondActivity启动ThirdActivity,再由ThirdActivity启动MainActivity,最后再启动SecondActivity。然后我们按两次回退键,发现回到了桌面了,这是为什么?

首先我们把MainActivity设为A,SecondActivity为B,ThirdActivity为C。

从Manifest文件中可以看到A为standard模式,任务栈为包名,而B和C是singleTask模式,任务栈为com.task1。

所以当我们从A启动B的时候,系统会为我们新建一个任务栈,就是com.task1,从而把B进栈。

从B启动C时,发现C所需要的任务栈com.task1已经存在,但是没有发现C的实例,这时候就创建C的实例并且进栈,这时com.task1里为BC

然后我们又从C启动A,由于A为standard模式,所以A会进入到C的任务栈,这时有两个任务栈存在,一个是为包名的任务栈,一个是为com.task1的任务栈。包名的任务栈里只有一个A,而com.task1的任务栈里现在是BCA

接着我们由A启动B,B是singleTask模式,而恰好当前栈里存在着B的实例,所以不会重新创建实例,而是把B调到栈顶,并且把前面的Activity通通出栈,此时com.task1的任务栈里就只剩下一个B了

最后我们按下一次回退键,当前B被出栈,com.task1任务栈被销毁,调出包名任务栈,也就是A,然后再按一次就退出程序了,这也就间接的证明了切换singleTask模式的Activity会把在它之上的Activity出栈。


写了这么多字累死我了

最后

爱生活,爱小丽,爱Android

上一篇下一篇

猜你喜欢

热点阅读