Android Acitivity啓動模式

Activity啓動模式對於我們很多應用中會有不同的要求,這兒簡單說一下Activity的四種啓動模式之間的差別

1.standard默認啓動模式,如果不在AndroidMainfest文件中配置,默認爲這個模式。

這種模式下,每次啓動這個Activity都會調onCreate方法創建新的實例。


示例代碼:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.i("MainActivity","onCreate  :");
    }
    public void clickButton(View view) {
        startActivity(new Intent(this, MainActivity.class));
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("MainActivity", " onResume instance :" + this.toString() + "  taskID :" + this.getTaskId());
    }
}


這兒寫一個按鈕,點擊按鈕啓動本身,Log可以看出,打印的instance 不相同,taskID 相同,點擊返回,不會直接退出應用,而是會閃一下,但是頁面顯示沒變,這就代表是同一個activity的不同實例。

2.singleTop唯一棧頂模式,當啓動該activity時,如果該activity有實例在棧頂,就不再重新創建新的實例,而是就用當前棧頂的實例,如果該activity沒有實例在棧頂就創建新的實例於棧頂。
    跟第一點中同樣的代碼,會發現每次點擊按鈕,不會走onCreate方法去創建新的實例。


3.singleTask當需要啓動的activity有實例存在於棧中,就不會再創建新的實例,而是把該實例上面的activity的實例出棧,讓該activity位於棧頂,用當前實例。

4.singleInstance該啓動模式會單獨開闢一個特殊的棧用於存放該activity的實例,當啓動別的activity的時候,跳到該進程所處的正常的那個棧,當再次啓動該activity的時候,重新跳轉到存放該activity的實例的特殊棧。


  好了,上面四種啓動方式都已經很詳細的說完了,現在我們來一個簡單的案例,看看最特殊的一種啓動方式singleInstance的特質。爲什麼說他最特殊呢?因爲只有這一種會另外開闢新棧,前面三種雖然有不同,但是因爲都是在同一個棧中,所以大同小異!

   現在我們有4個Activity,類名稱如下:MainActivity,Main1Activity,Main2Activity,Main3Activity.清單文件中的啓動方式,除了Main2Activity之外,其他三個都是默認的啓動方式standard啓動模式。

清單文件:

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <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=".Main1Activity" />
    <activity
        android:name=".Main2Activity"
        android:launchMode="singleInstance" />
    <activity
        android:name=".Main3Activity"/>
</application>

佈局文件都一樣,就是有一個按鈕,點擊啓動下一個Activity,button上顯示的是當前activity的名字:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.dragon.upandroiddemos.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="clickButton"
        android:text="MainActivity"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

Activity中的代碼也一樣,就是啓動下一個activity,並且將當前activity所在棧的ID打印出來:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void clickButton(View view) {

        startActivity(new Intent(this, Main1Activity.class));
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i("MainActivity","onResume taskID :"+getTaskId());
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i("MainActivity","onStart  :");
    }
}

現在我們做這樣的操作,在每一個activity中去啓動下一個activity,啓動順序如下:Main----->Main1---->Main2----->Main3----->Main。現在我們來看看log,然後再分析一下。


好了,現在我們再按返回鍵,觀察log結果:

很明顯除了Main2在12167棧中,其他三個都在12166棧中。並且按返回鍵的時候,沒有按啓動的順序來返回,現在我們來說說這個過程。

啓動過程是調用startActivity方法去創建新的activity並且將當前窗口交給被啓動的activity,這個是按前面所說的啓動方式正常的啓動,沒有什麼可質疑的。過程如下圖:


現在的問題是,現在按返回鍵的時候,從前面的log很明顯的看出,在Main3返回的時候,沒有返回到Main2,而是直接回到了Main1。注意這兒就對了。其實系統返回鍵是將activity棧中的activity出棧的一個過程,也就是說這個過程會連續去操作12166中所存在的activity。當12166棧中的所有activity出棧之後,12167還在當前應用進程中,這時候無法直接退出進程的。需要將12167中的activity也出棧之後將12167棧回收掉。所以纔會有上面的這個過程。


好了講到這兒就差不多完了,網友可以自己試驗一下將Main3也該成singleInstance啓動模式,看看上面的操作會是一個什麼效果。這兒我就不再試了!




發佈了34 篇原創文章 · 獲贊 23 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章