Android提供了四种Activity启动方式:
-
标准模式(standard)
-
栈顶复用模式(singleTop)
-
栈内复用模式(singleTask)
-
单例模式(singleInstance)
Activity的管理是采用任务栈的形式,任务栈采用“后进先出”的栈结构。
标准模式:
该模式也是系统的默认模式,当我们多次创建Activity时,系统会将创建的实例一一放入任务栈,不管它是否已经被创建过。该模式下,谁启动了这个Activity,它就运行在启动的它的Activity所在的栈中。
例如:Activity A启动了Activity B,则就会在A所在的栈顶压入一个新的Activity。
特殊情况,如果在Service或Application中启动一个Activity,其并没有所谓的任务栈,可以使用标记位Flag来解决。解决办法:为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,创建一个新栈。应用场景: 绝大多数Activity。如果以这种方式启动的Activity被跨进程调用,在5.0之前新启动的Activity实例会放入发送Intent的Task的栈的顶部,尽管它们属于不同的程序,这似乎有点费解看起来也不是那么合理,所以在5.0之后,上述情景会创建一个新的Task,新启动的Activity就会放入刚创建的Task中,这样就合理的多了。
栈顶复用模式:
顾名思义,在这种模式下,如果有新的Activity已经存在任务栈的栈顶,那么此Activity就不会被重新创建新实例,而是复用已存在任务栈栈顶的Activity,并回调如下方法:
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); } //通过此方法的参数,我们可以获取当前请求的相关信息,此时Activity的onCreate、onStart方法不会被调用,因为Activity并没有被重建。
ps:如果栈顶不是新建的Activity,就会创建该Activity新的实例,并放入栈顶。
应用场景:这种模式通常比较适用于接收到消息后显示的界面,比如在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。当然实际的开发过程中,测试妹纸没准给你提过这样的bug:某个场景下连续快速点击,启动了两个Activity。如果这个时候待启动的Activity使用singleTop模式也是可以避免这个Bug的。同standard模式,如果是外部程序启动singleTop的Activity,在Android 5.0之前新创建的Activity会位于调用者的Task中,5.0及以后会放入新的Task中。
栈内复用模式:
该模式是一种单例模式,即一个栈内只有一个该Activity实例。该模式,可以通过在AndroidManifest文件的Activity中指定该Activity需要加载到那个栈中,即singleTask的Activity可以指定想要加载的目标栈。singleTask和taskAffinity配合使用,指定开启的Activity加入到哪个栈中。<activity android:name=".Activity1" android:launchMode="singleTask" android:taskAffinity="com.lvr.task" android:label="@string/app_name"> </activity>
关于taskAffinity的值: 每个Activity都有taskAffinity属性,这个属性指出了它希望进入的Task。如果一个Activity没有显式的指明该Activity的taskAffinity,默认为应用的包名。
执行逻辑:
在这种模式下,如果Activity指定的栈不存在,则创建一个栈,并把创建的Activity压入栈内。如果Activity指定的栈存在,如果其中没有该Activity实例,则会创建Activity并压入栈顶,如果其中有该Activity实例,则把该Activity实例之上的Activity杀死清除出栈,重用并让该Activity实例处在栈顶,然后调用 onNewIntent()方法。
应用场景: 大多数App的主页(频繁使用的主架构)。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。在跨应用Intent传递时,如果系统中不存在singleTask Activity的实例,那么将创建一个新的Task,然后创建SingleTask Activity的实例,将其放入新的Task中。
单实例模式:
作为栈内复用模式的加强版,打开该Activity时,直接创建一个新的任务栈,并创建该Activity实例放入新栈中。一旦该模式的Activity实例已经存在于某个栈中,任何应用再激活该Activity时都会重用该栈中的实例。
应用场景:这个经常使用于系统中的应用,比如Launch、锁屏键、来电显示等等,整个系统中仅仅有一个呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。
启动模式的使用方式
-
在 Manifest.xml中指定Activity启动模式
一种静态的指定方法,在Manifest.xml文件里声明Activity的同一时候指定它的启动模式,这样在代码中跳转时会依照指定的模式来创建Activity。样例以下:
<activity android:launchMode="启动模式" //属性 //standard:标准模式 //singleTop:栈顶复用模式 //singleTask:栈内复用模式 //singleInstance:单例模式 //如不设置,Activity的启动模式默认为**标准模式(standard)** </activity>
-
启动Activity时。在Intent中指定启动模式去创建Activity一种动态的启动模式,在new 一个Intent后,通过Intent的addFlags方法去动态指定一个启动模式。样例以下:
Intent intent = new Intent(); intent.setClass(context, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
注意:以上两种方式都能够为Activity指定启动模式,可是二者还是有差别的。
- 优先级:动态指定方式即第二种比第一种优先级要高,若两者同一时候存在,以第二种方式为准。
- 限定范围:第一种方式无法为Activity直接指定 FLAG_ACTIVITY_CLEAR_TOP 标识,第二种方式无法为 Activity指定 singleInstance 模式。
Activity 的 Flags
标记位既能够设定Activity的启动模式,如同上面介绍的,在动态指定启动模式:比方 FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_SINGLE_TOP 等。它还能够影响Activity 的运行状态 ,比方 FLAG_ACTIVITY_CLEAN_TOP 和 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 等。
-
FLAG_ACTIVITY_NEW_TASK
作用是为Activity指定 “SingleTask”启动模式。跟在AndroidMainfest.xml指定效果同样。
-
FLAG_ACTIVITY_SINGLE_TOP
作用是为Activity指定 “SingleTop”启动模式,跟在AndroidMainfest.xml指定效果同样。
-
FLAG_ACTIVITY_CLEAN_TOP
具有此标记位的Activity,当它启动时,在同一个任务栈中所有位于它上面的Activity都要出栈。如果和singleTask模式一起出现,若被启动的Activity已经存在栈中,则清除其之上的Activity,并调用该Activity的onNewIntent()方法。如果被启动的Activity采用standard模式,那么该Activity连同之上的所有Activity出栈,然后创建新的Activity实例并压入栈中。
-
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有此标记位的Activity不会出如今历史Activity的列表中,使用场景:当某些情况下我们不希望用户通过历史列表回到Activity时,此标记位便体现了它的效果。它等同于在xml中指定Activity的属性:
android:excludeFromRecents=“trure”
-
网友评论