Activity的启动模式简介

  在android应用开发中,打造良好的用户体验是非常重要的。而在用户体验中,界面的引导和跳转是值得深入研究的重要内容。在开发中,与界面跳转联系比较紧密的概念是Task(任务)和Back Stack(回退栈)。activity的启动模式会影响Task和Back Stack的状态,进而影响用户体验。除了启动模式之外,Intent类中定义的一些标志(以FLAG_ACTIVITY开头)也会影响Task和Back Stack的状态。

  Task是一个存在于Framework层的概念,容易与它混淆的有Application(应用)和Process(进程)。在开始介绍Activity的启动模式的使用之前,首先对这些概念做一个简单的说明和区分。

  一 Application,Task和Process的区别与联系

  application一般称为“应用”或“应用程序”,在android中,总体来说一个应用就是一组组件的集合。众所周知,android是在应用层组件化程度非常高的系统,android开发的第一课就是学习android的四大组件。当我们写完了多个组件,并且在manifest文件中注册了这些组件之后,把这些组件和组件使用到的资源打包成apk,我们就可以说完成了一个application。application和组件的关系可以在manifest文件中清晰地体现出来。如下所示:
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest android:versionCode="1"
 3         android:versionName="1"
 4         xmlns:android="http://schemas.android.com/apk/res/android"
 5         package="com.example.android.myapp">
 6 
 7     <application android:label="@string/app_name">
 8         <activity android:name=".MyActivity" android:label="@string/app_nam">
 9             <intent-filter>
10                 <action android:name="android.intent.action.MAIN" />
11                 <category android:name="android.intent.category.LAUNCHER" />
12             </intent-filter>
13         </activity>
14         <receiver android:name=".MyReceiver"/>
15         <provider android:name=".MyProvider"/>
16         <service android:name=".MyService"/>
17     </application>
18 </manifest>

  application是由四大组件组成的,之前我们讲过,在app安装时主要就是读取manifest的信息,将所有的组件解析出来,以便在运行时对组件进行实例化和调度。

  task是一组相互关联的activity的集合,它是存在于framework层的一个概念,控制界面的跳转和返回。这个task存在于一个称为back stack的数据结构中,也就是说,framework是以栈的形式管理用户开启的activity。这个栈的基本行为是,当用户在多个activity之间跳转时,执行压栈操作,当用户按返回键时,执行出栈操作。任务栈的操作可以如下图所示:

  process一般翻译成进程,进程是操作系统内核中的一个概念,表示直接受内核调度的执行单位。在应用程序的角度看,我们用java编写的应用程序,运行在dalvik虚拟机中,可以认为一个运行中的dalvik虚拟机实例占有一个进程,所以,在默认情况下,一个应用程序的所有组件运行在同一个进程中。但是这种情况也有例外,即,应用程序中的不同组件可以运行在不同的进程中。只需要在manifest中用process属性指定组件所运行的进程的名字。如下所示,这样的话这个MyActivity会运行在一个独立的进程remote中:

1  <activity android:name=".MyActivity" android:label="@string/app_nam"
2         android:process=":remote">
3  </activity>

  二 Activity四种启动模式详解

  activity有四种启动模式,分别为standard(标准),singleTop(栈顶),singleTask(单任务),singleInstance(单例)。如果要使用这四种启动模式,必须在manifest文件中<activity>标签中的launchMode属性中配置,如下:

1         <activity android:name=".app.InterstitialMessageActivity"
2                   android:label="@string/interstitial_label"
3                   android:theme="@style/Theme.Dialog"
4                   android:launchMode="singleTask"
5         </activity>

  Activity的启动模式也可以在intent的标志位中设置,标志位所代表的启动方式我们能从字面意思上清晰的了解到:

1 Intent.FLAG_ACTIVITY_NEW_TASK
2 Intent.FLAG_ACTIVITY_SINGLE_TOP
3 Intent.FLAG_ACTIVITY_CLEAR_TOP
4 Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT

  下面就简单介绍一下这四种启动方式,当然要更好地理解还是推荐看官方文档和源码。

standard(FLAG_ACTIVITY_NEW_TASK)

标准启动模式,也是activity的默认启动模式。在这种模式下启动的activity可以被多次实例化,即在同一个任务中可以存在多个activity的实例,每个实例都会处理一个Intent对象。如果Activity A的启动模式为standard,并且A已经启动,在A中再次启动Activity A,即调用startActivity(new Intent(this,A.class)),会在A的上面再次启动一个A的实例,即当前的桟中的状态为A-->A。
 

singleTop(FLAG_ACTIVITY_SINGLE_TOP

如果一个以singleTop模式启动的activity的实例已经存在于任务桟的桟顶,那么再启动这个Activity时,不会创建新的实例,而是重用位于栈顶的那个实例,并且会调用该实例的onNewIntent()方法将Intent对象传递到这个实例中。举例来说,如果A的启动模式为singleTop,并且A的一个实例已经存在于栈顶中,那么再调用startActivity(new Intent(this,A.class))启动A时,不会再次创建A的实例,而是重用原来的实例,并且调用原来实例的onNewIntent()方法。这是任务桟中还是这有一个A的实例。
如果以singleTop模式启动的activity的一个实例已经存在与任务桟中,但是不在桟顶,那么它的行为和standard模式相同,也会创建多个实例。
 

singleTask(FLAG_ACTIVITY_CLEAR_TOP

谷歌的官方文档上称,如果一个activity的启动模式为singleTask,那么系统总会在一个新任务的最底部(root)启动这个activity,并且被这个activity启动的其他activity会和该activity同时存在于这个新任务中。如果系统中已经存在这样的一个activity则会重用这个实例,并且调用他的onNewIntent()方法。即,这样的一个activity在系统中只会存在一个实例。 

singleInstance(FLAG_ACTIVITY_BROUGHT_TO_FRONT)

总是在新的任务中开启,并且这个新的任务中有且只有这一个实例,也就是说被该实例启动的其他activity会自动运行于另一个任务中。当再次启动该activity的实例时,会重用已存在的任务和实例。并且会调用这个实例的onNewIntent()方法,将Intent实例传递到该实例中。和singleTask相同,同一时刻在系统中只会存在一个这样的Activity实例。
posted @ 2014-12-18 10:11  Simba.Chen  阅读(350)  评论(0编辑  收藏  举报