【Android基礎知識】Activity的四種啓動模式

Android的Activity有四種啓動模式,在實際的應用中,我們應該根據特定的需求爲每個活動指定特定的啓動模式,這四種啓動模式分別是

standard、singleTop、singleTask、singleInstance

1.standard

standard 是活動默認的啓動模式,在不進行顯式指定的情況下,所有活動都會自動使用這種啓動模式。 Android 使用返回棧來管理活動,在 standard 模式(即默認情況)下,每當啓動一個新的活動,它就會在返回棧中入棧,並處於棧頂的位置。對於使用standard 模式的活動,系統不會在乎這個活動是否已經在返回棧中存在,每次啓動都會創建該活動的一個新的實例。

例子:

public class FirstActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("StartMode","FirstActivity "+FirstActivity.this);
        setContentView(R.layout.activity_first);
    }
    public void startIntent(View view){
    	Intent intent = new Intent(FirstActivity.this,FirstActivity.class);
    	startActivity(intent);
    }
}
該Activity重複啓動自己,log信息顯示如下,可以發現每次都會重新創建一個Activity,棧裏有四個FirstActivity,需要按四次back鍵纔可以退出。

2.singleTop

在有些情況下,你會覺得 standard 模式不太合理。活動明明已經在棧頂了,爲什麼再次啓動的時候還要創建一個新的活動實例呢?這只是系統默認的一種啓動模式而已,你完全可以根據自己的需要進行修改,比如說使用 singleTop 模式。當活動的啓動模式指定爲 singleTop,在啓動活動時如果發現返回棧的棧頂已經是該活動,則認爲可以直接使用它,不會再創建新的活動實例。

<activity
            android:name=".FirstActivity"
            android:label="@string/app_name" 
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
這時候不管再啓動多少次,都只會有一個FirsetActivity實例


如果FirstActivity沒有在棧頂的話,再次啓動則仍然會創建一個新的實例。

3.SingleTask

使用 singleTop 模式可以很好地解決重複創建棧頂活動的問題,但是正如你在上一節所看到的,如果該活動並沒有處於棧頂的位置,還是可能會創建多個活動實例的。那麼有沒有什麼辦法可以讓某個活動在整個應用程序的上下文中只存在一個實例呢?這就要藉助singleTask模式來實現了。當活動的啓動模式指定爲 singleTask,每次啓動該活動時系統首先會在返回棧中檢查是否存在該活動的實例,如果發現已經存在則直接使用該實例,並把在這個活動之上的所有活動統統出棧,如果沒有發現就會創建一個新的活動實例。

修改Activity的啓動模式

<activity
            android:name=".FirstActivity"
            android:label="@string/app_name" 
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
在FirstActivity的onRestart方法中添加log信息

 @Override
    protected void onRestart() {
    	Log.i("StartMode","onRestart");
    	super.onStart();
    }
在SecondActivity的onDestory方法中添加log信息

@Override
	protected void onDestroy() {
		Log.i("StartMode","SecondActivity onDestory");
		super.onDestroy();
	}
操作步驟,啓動FirstActivity,點擊按鈕跳轉到SecondActivity,再次點擊按鈕,跳轉到FirstActivity,日誌信息如下:


直接調用了onRestart方法,沒有重新進行創建,並且SecondActivity被從棧中彈出銷燬。

4.singleInstance

不同於以上三種啓動模式,指定爲 singleInstance模式的活動會啓用一個新的返回棧來管理這個活動(其實如果 singleTask模式指定了不同的 taskAffinity,也會啓
動一個新的返回棧)。那麼這樣做有什麼意義呢?想象以下場景,假設我們的程序中有一個活動是允許其他程序調用的,如果我們想實現其他程序和我們的程序可以共享這個活動的實例,應該如何實現呢?使用前面三種啓動模式肯定是做不到的,因爲每個應用程序都會有自己的返回棧,同一個活動在不同的返回棧中入棧時必然是創建了新的實例。而使用singleInstance模式就可以解決這個問題,在這種模式下會有一個單獨的返回棧來管理這個活動,不管是哪個應用程序來訪問這個活動,都共用的同一個返回棧,也就解決了共享活動實例的問題。
設置SecondActivity的啓動模式爲singleInstance

<activity
            android:name=".SecondActivity"
            android:label="@string/title_activity_main"
            android:launchMode="singleInstance" >
</activity>
分別再FirstActivity,SecondActivity,ThirdActivity的oncreate方法中加上log信息

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("StartMode","FirstActivity Task id is "+this.getTaskId());
        setContentView(R.layout.activity_first);
    }
@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.i("StartMode","SecondActivity Task id is "+this.getTaskId());
		setContentView(R.layout.activity_main);
	}
@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.i("StartMode","ThirdActivity Task id is "+this.getTaskId());
		setContentView(R.layout.activity_third);
	}
操作步驟,從FirstActivity跳轉到SecondActivity再跳轉到ThirdActivity  Log信息打印如下:


可以發現SecondActiviy的Task ID和其他的不同,所以表明它新創建了一個棧,而且這個棧只有SecondActivity這一個活動。按下 Back鍵進行返回,ThirdActivity直接返回到了 FirstActivity,再按下 Back 鍵又會返回到 SecondActivity,再按下 Back 鍵纔會退出程序,由於 FirstActivity 和 ThirdActivity 是存放在同一個返回棧裏的,當在ThirdActivity 的界面按下 Back 鍵,ThirdActivity 會從返回棧中出棧,那麼 FirstActivity 就成爲了棧頂活動顯示在界面上,因此也就出現了從 ThirdActivity 直接返回到 FirstActivity 的情況。然後在 FirstActivity 界面再次按下 Back 鍵,這時當前的返回棧已經空了,於是就顯示了另一個返回棧的棧頂活動,即 SecondActivity。最後再次按下 Back 鍵,這時所有返回棧都已經空了,也就自然退出了程序。

本文參考 《第一行代碼》






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