Activity的四種啓動方式

Activity的四種啓動模式

Android開發者在AndroidManifest文件中一共設計了四種啓動模式

  • standard
  • singleTop
  • singleTask
  • singleInstance

一、Android 任務棧

在瞭解Acvitity的四種啓動模式之前,我們必須瞭解Android任務棧的概念

棧:先進後出的線性表
一個android應用程序功能通常會被拆分爲多個Activity,而各個Activity之間通過Intent進行連接,android系統通過棧結構來保存整個程序的Activity,棧底的原始是整個棧任務的發起者。
正常情況下,當一個Activity啓動了另一個Activity的時候,新啓動的Activity就會置於任務棧的頂端,二啓動它的Activity雖然功成身退,但依然保留在任務棧中,處於停止狀態(如果沒有finish),當用戶按下返回鍵或者調用finish()方法時,系統會移除頂部的Activity,讓後面的Activity恢復活動狀態。但是,可以給Activity設置一些“特權”,來打破這種“和諧”的模式。這種特權,就是通過在AndroidManifest.xml文件中的屬性android:launchMode來設置或者通過Intent的flag來設置的。

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

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        Intent intent = new Intent(this,MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
     // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

二、四種啓動模式

  • standard
  • singleTop
  • singleTask
  • singleInstance

2.1 standard

默認啓動模式,當不指定Activity的啓動模式,則使用這種啓動方式啓動Activity;這種啓動方式每次都會創建新的實例,新的activity會覆蓋在原來的activity上。

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.e(TAG, "onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testLauncherMode();
            }
        });
    }

    void testLauncherMode() {
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
    }

這裏寫圖片描述
模型如下
這裏寫圖片描述

2.2 singleTop

如果指定啓動模式爲singleTop模式,那麼在啓動時,系統會判斷當前棧頂的Activity是不是要啓動的Activity,如果是則不創建新的Activity而直接引用這個Activity;如果不是,則創建新的Activity.

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate");
        setContentView(R.layout.view_second);

        Button button = (Button) findViewById(R.id.button2);
        Button btnMySelf = findViewById(R.id.button3);
        btnMySelf.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startMySelf();
            }
        });
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                testSingleTopLauncherMode();
            }
        });
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.e(TAG,"onNewIntent");
    }

這裏寫圖片描述
模型如下
這裏寫圖片描述

2.3 singleTask

參考自
作者:JxYoung
鏈接:https://www.jianshu.com/p/4c8d6e2117ac
來源:簡書

這種啓動模式的Activity在Android系統中只允許存在一個實例

如果系統中已經存在了該種啓動模式的目標Activity,則系統並不會重新創建一個目標Activity,而是首先將持有目標Activity的整個任務棧都會被置於前臺(用戶可見),並且通過onNewIntent(
)方法將啓動目標Activity的Intent傳遞給目標Activity,置於目標Activity拿到這個Intent之後要做什麼操作,系統就不管了,隨便你拿來幹什麼。

但是這裏有個問題,就是目標Activity和源Activity是不是來自同一應用。

源Activity和目標Activity來自同一個應用

這種情況還要分兩種情況說:

當前系統中還沒有目標Activity的實例
這種情況最簡單,直接在當前的任務棧中創建SingleTask模式的Activity並置於棧頂即可。

當前系統中已經存在目標Activity的實例
這種情況比較特殊,因爲系統會把任務棧中目標Activity之上的所有Activity銷燬,以讓目標Activity處在棧頂的位置。

這裏還要還要再提醒大家的是,因爲目標Activity已經存在,系統不會重新創建,而是通過onNewIntent()的方式把Intent傳遞過來,這點和singleTop模式有些類似
這裏寫圖片描述

這裏寫圖片描述

源Activity和目標Activity來自不同應用 這種情況也要分兩種情況說:

當前系統中還沒有目標Activity的實例
這時系統首先會看任務管理器中是否有目標Actvity所在應用的任務棧?如果有的話,那就直接在目標Activity所在應用的任務棧的棧頂創建即可。

如果任務管理器中沒有目標Activity所在應用的任務棧,系統就會創建其所在應用的任務棧和目標Activity,並且把目標Activity作爲新建任務棧的根Activity。如下圖所示
這裏寫圖片描述

當前系統中已經存在目標Activity的實例
目標Activity所在任務棧會被置於前臺(即用戶可見),而且也會把目標Activity之上的所有Actvity全部銷燬。

2.4 singleInstance

這種啓動模式和singleTask幾乎一樣,它也只允許系統中存在一個目標Activity,包括上面我們所說的SingleTask的一些特性singleInstance都有。singleInstance翻譯過來是單例的意思:TA有兩層含義:1.告訴系統,我是獨一無二的,2.告訴任務棧我是獨一無二的,也就是說,任務棧中除了我不能再有其他Activity。

所以,如果要啓動singleInstance模式的Activity,那隻能新創建一個任務棧用來放它,因爲人家說了,“我是獨一無二的!”。同樣的,如果從這種啓動模式的Activity中啓動別的Activity,那不好意思,我不管你是不是和我處在同一個應用,我所在的任務棧只能擁有我一個人,您吶,另外讓系統給你創建一個任務棧待着去吧。

三、啓動模式的使用

3.1 在AndroidManifest.xml文件中配置

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

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

3.2 通過Intent添加標誌來識別

        Intent intent = new Intent(this,MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
     // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

常用的Flag

  • INTENT.FLAG_ACTIVITY_NEW_TASK

    使用一個新的Task來啓動一個Activity,但啓動的每個Activity都將在一個系的Task中。該Flag通常用來從Service中啓動Activity的場景,由於在Service中並不存在Activity棧,所以使用該Flag來創建一個新的Activity棧,並創建新的Activity實例。

  • INTENT.FLAG_ACTIVITY_SINGLE_TOP

    等同於android:launchMode=”singleTop”

  • INTENT.FLAG_ACTIVITY_CLEAR_TOP

    等同於android:launchMode=”singleTask”

  • INTENT.FLAG_ACTIVITY_NO_HISTORY

    使用這種模式啓動Activity,當該Activity啓動其他Activity後,該Activity就消失了,不會保留在Activity棧中,例如A-B,B以這種模式啓動C,C在啓動D,則當前Activity棧爲ABD。

文章寫到這,希望對給位有所幫助,謝謝觀看。

參考文獻:
https://www.jianshu.com/p/4c8d6e2117ac
http://blog.csdn.net/x283930450/article/details/70597555

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章