Android:四种启动模式分析

在一个项目中会包括着多个Activity,系统中使用任务栈来存储建立的Activity实例,任务栈是一种“后进先出”的栈结构。举个栗子,若咱们屡次启动同一个Activity。系统会建立多个实例依次放入任务栈中。当按back键返回时,每按一次,一个Activity出栈,直到栈空为止。当栈中无不论什么Activity。系统就会回收此任务栈。android

上面这个样例中的Activity并无设置启动模式,你会发现屡次启动同一个Activity。而系统却建立了多个实例,白白浪费内存,这样的状况Android早就替咱们考虑好了。Android为Activity 的建立提供了4种启动模式,而依据实际应用场景的不一样。为Activity 选择不一样的启动模式,最大化下降了每次都需要在栈中建立一个新的Activity的压力,下降内存使用。ide

启动模式的具体说明和使用场景?如下依据这篇博文来一一解惑。.net

一. Android启动模式具体解释设计


1. Standard 标准模式
说明: Android建立Activity时的默认模式,假设没有为Activity设置启动模式的话,默以为标准模式。每次启动一个Activity都会又一次建立一个新的实例入栈,不管这个实例是否存在。xml

生命周期:如上所看到的,每次被建立的实例Activity 的生命周期符合典型状况,它的onCreate、onStart、onResume都会被调用。blog

举例:此时Activity 栈中以此有A、B、C三个Activity,此时C处于栈顶,启动模式为Standard 模式。生命周期

若在C Activity中加入点击事件,需要跳转到还有一个同类型的C Activity。结果是还有一个C Activity进入栈中,成为栈顶。 事件


2. SingleTop 栈顶复用模式
说明:分两种处理状况:需要建立的Activity已经处于栈顶时,此时会直接复用栈顶的Activity。不会再建立新的Activity;若需要建立的Activity不处于栈顶,此时会又一次建立一个新的Activity入栈,同Standard模式同样。ip

生命周期:若状况一中栈顶的Activity被直接复用时,它的onCreate、onStart不会被系统调用,因为它并无发生改变。但是一个新的方法 onNewIntent会被回调(Activity被正常建立时不会回调此方法)。内存

举例:此时Activity 栈中以此有A、B、C三个Activity,此时C处于栈顶,启动模式为SingleTop 模式。状况一:在C Activity中加入点击事件,需要跳转到还有一个同类型的C Activity。

结果是直接复用栈顶的C Activity。

状况二:在C Activity中加入点击事件,需要跳转到还有一个A Activity。结果是建立一个新的Activity入栈。成为栈顶。


3. SingleTask 栈内复用模式
说明:若需要建立的Activity已经处于栈中时,此时不会建立新的Activity,而是将存在栈中的Activity上面的其余Activity全部销毁,使它成为栈顶。

生命周期:同SingleTop 模式中的状况一一样。仅仅会又一次回调Activity中的 onNewIntent方法

举例:此时Activity 栈中以此有A、B、C三个Activity。此时C处于栈顶,启动模式为SingleTask 模式。

状况一:在C Activity中加入点击事件,需要跳转到还有一个同类型的C Activity。结果是直接用栈顶的C Activity。状况二:在C Activity中加入点击事件,需要跳转到还有一个A Activity。

结果是将A Activity上面的B、C全部销毁,使A Activity成为栈顶。 


4. SingleInstance 单实例模式
说明: SingleInstance比較特殊,是全局单例模式,是一种增强的SingleTask模式。它除了具备它全部特性外,还增强了一点:具备此模式的Activity仅仅能单独位于一个任务栈中。

这个常用于系统中的应用,好比Launch、锁屏键的应用等等,整个系统中仅仅有一个!因此在咱们的应用中通常不会用到。了解就能够。

举例:比方 A Activity是该模式,启动A后。系统会为它建立一个单独的任务栈,因为栈内复用的特性。兴许的请求均不会建立新的Activity,除非这个独特的任务栈被系统销毁。

二.启动模式的使用方式
1. 在 Manifest.xml中指定Activity启动模式
一种静态的指定方法,在Manifest.xml文件里声明Activity的同一时候指定它的启动模式,这样在代码中跳转时会依照指定的模式来建立Activity。样例例如如下:

        <activity android:name="..activity.MultiportActivity" android:launchMode="singleTask"/>
2. 启动Activity时。在Intent中指定启动模式去建立Activity
一种动态的启动模式,在new 一个Intent后,经过Intent的addFlags方法去动态指定一个启动模式。样例例如如下:

        Intent intent = new Intent();
        intent.setClass(context, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
注意:以上两种方式都可以为Activity指定启动模式,但是两者仍是有差异的。

(1)优先级:动态指定方式即另一种比第一种优先级要高,若二者同一时候存在,以另一种方式为准。


(2)限定范围:第一种方式没法为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 等。

如下介绍几个基本的标记位,切勿死记,理解几个就能够,需要时再查官方文档。

1. FLAG_ACTIVITY_NEW_TASK
做用是为Activity指定 “SingleTask”启动模式。跟在AndroidMainfest.xml指定效果一样。

2. FLAG_ACTIVITY_SINGLE_TOP
做用是为Activity指定 “SingleTop”启动模式,跟在AndroidMainfest.xml指定效果一样。

3. FLAG_ACTIVITY_CLEAN_TOP
具备此标记位的Activity,启动时会将与该Activity在同一任务栈的其余Activity出栈。通常与SingleTask启动模式一块儿出现。它会完毕SingleTask的做用。但事实上SingleTask启动模式默认具备此标记位的做用

4.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具备此标记位的Activity不会出现在历史Activity的列表中,使用场景:当某些状况下咱们不但愿用户经过历史列表回到Activity时,此标记位便体现了它的效果。它等同于在xml中指定Activity的属性:

android:excludeFromRecents="trure"
四. 启动模式的实际应用场景
这四种模式中的Standard模式是最普通的一种,没有什么特别注意。而SingleInstance模式是整个系统的单例模式,在咱们的应用中通常不会应用到。因此,这里就具体解说 SingleTop 和 SingleTask模式的运用场景:

1. SingleTask模式的运用场景
最多见的应用场景就是保持咱们应用开启后仅仅有一个Activity的实例。最典型的样例就是应用中展现的主页(Home页)。

假设用户在主页跳转到其余页面,运行屡次操做后想返回到主页,假设不使用SingleTask模式,在点击返回的过程当中会屡次看到主页,这明显就是设计不合理了。

2. SingleTop模式的运用场景
假设你在当前的Activity中又要启动同类型的Activity,此时建议将此类型Activity的启动模式指定为SingleTop,可以下降Activity的建立,节省内存!

3. 注意:复用Activity时的生命周期回调
这里还需要考虑一个Activity跳转时携带页面參数的问题。

因为当一个Activity设置了SingleTop或者SingleTask模式后,跳转此Activity出现复用原有Activity的状况时,此Activity的onCreate方法将不会再次运行。onCreate方法仅仅会在第一次建立Activity时被运行。

而通常onCreate方法中会进行该页面的数据初始化、UI初始化,假设页面的展现数据无关页面跳转传递的參数,则没必要操心此问题,若页面展现的数据就是经过getInten() 方法来获取,那么问题就会出现:getInten()获取的一直都是老数据,根本没法接收跳转时传送的新数据!

如下,经过一个样例来具体解释:

Manifest.xml
        <activity
            android:name=".activity.CourseDetailActivity"
            android:launchMode="singleTop"
            android:screenOrientation="portrait" />
public class CourseDetailActivity extends BaseActivity{
  ......
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_course_detail_layout);
        initData();
        initView();
    }
 
   //初始化数据
    private void initData() {
        Intent intent = getIntent();
        mCourseID = intent.getStringExtra(COURSE_ID);
    }
 
    //初始化UI
    private void initView() {
    ......
    }
    ......
}
以上代码中的CourseDetailActivity在配置文件里设置了启动模式是SingleTop模式,依据上面启动模式的介绍可得知,当CourseDetailActivity处于栈顶时。再次跳转页面到CourseDetailActivity时会直接复用原有的Activity,而且此页面需要展现的数据是从getIntent()方法得来,但是initData()方法不会再次被调用,此时页面就没法显示新的数据。

固然这样的状况系统早就为咱们想过了,这时咱们需要另一个回调 onNewIntent(Intent intent)方法。此方法会传入最新的intent,这样咱们就可以解决上述问题。这里建议的方法是又一次去setIntent。而后又一次去初始化数据和UI。代码例如如下所看到的:

/*
* 复用Activity时的生命周期回调
*/
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        initData();
        initView();
    }
这样,在一个页面中可以反复跳转并显示不一样的内容。

那么onNewIntent都会在什么状况下调用呢?

前提:ActivityA已经启动过,处于当前应用的Activity堆栈中; 

当ActivityA的LaunchMode为SingleTop时,若是ActivityA在栈顶,且如今要再启动ActivityA,这时会调用onNewIntent()方法 

当ActivityA的LaunchMode为SingleInstance,SingleTask时,若是已经ActivityA已经在堆栈中,那么此时会调用onNewIntent()方法 

当ActivityA的LaunchMode为Standard时,因为每次启动ActivityA都是启动新的实例,和原来启动的不要紧,因此不会调用原来ActivityA的onNewIntent方法

And 生命周期流程

singleInstance:
第一次进入:onCreate onStart
在栈顶再次进入: onNewIntent
不在栈顶再次进入:onNewIntent onRestart onStart
按home键再次进入:onRestart onStart

standard:
第一次进入:onCreate onStart
在栈顶再次进入: onCreate onStart
不在栈顶再次进入:onCreate onStart

按home键  onPause--onSaveInstanceState--onStop(未勾选“不保留活动‘’)

             勾选了的话  onPause--onSaveInstanceState--onStop--onDestroy

再次进入(未勾选“不保留活动‘’): 主activity  onNewIntent--onRestart-onStart    

 非主activity onRestart-onStart  

按返回键:onPause--onStop--onDestroy (不走save了)从新进入onCreate onStart


singleTop:
第一次进入:onCreate onStart
在栈顶再次进入:onNewIntent
不在栈顶再次进入:onCreate onStart
按home键   再次进入:onRestart onStart

singleTask:
第一次进入:onCreate onStart
在栈顶再次进入:onNewIntent
不在栈顶再次进入:onNewIntent onRestart onStart
按home键再次进入:onRestart onStart


Activity的四种启动模式:  
    1. standard  
        默认启动模式,每次激活Activity时都会建立Activity,并放入任务栈中,永远不会调用onNewIntent()。  
    2. singleTop  
        若是在任务的栈顶正好存在该Activity的实例, 就重用该实例,并调用其onNewIntent(),否者就会建立新的实例并放入栈顶(即便栈中已经存在该Activity实例,只要不在栈顶,都会建立实例,而不会调用onNewIntent(),此时就跟standard模式同样)。  
    3. singleTask  
        若是在栈中已经有该Activity的实例,就重用该实例(会调用实例的onNewIntent())。重用时,会让该实例回到栈顶,所以在它上面的实例将会被移除栈。若是栈中不存在该实例,将会建立新的实例放入栈中(此时不会调用onNewIntent())。   
    4. singleInstance  
        在一个新栈中建立该Activity实例,并让多个应用共享改栈中的该Activity实例。一旦改模式的Activity的实例存在于某个栈中,任何应用再激活改Activity时都会重用该栈中的实例,其效果至关于多个应用程序共享一个应用,无论谁激活该Activity都会进入同一个应用中。  

当调用到onNewIntent(intent)的时候,须要在onNewIntent() 中使用setIntent(intent)赋值给Activity的Intent.不然,后续的getIntent()都是获得老的Intent。

相关文章
相关标签/搜索