Activity的四種啓動模式淺析

初看這個博文名,我都矇蔽了,Activity的啓動模式居然能扯到內存問題,還有內存泄漏問題,
WTF!!!不要方,小司機我帶你理解和稍微深入的探討一下Activity的四種啓動模式對內存的影響和在何種情況下應該使用這四大法王之一呢?

首先我們探討一下千篇一律的Activity的四種啓動模式

不寫Demo,你就聽我說就行了。

Activity的啓動方式有四種

standard

singleTop

singleTask

singleInstance

講解啓動模式之前有必要先講解一下“任務棧”的概念;

任務棧

每個應用都有一個任務棧,是用來存放Activity的,功能類似於函數調用的棧,先後順序代表了Activity的出現順序;比如打開ActivityYa–>ActivityMai–>ActivityDai,則任務棧相應的順序圖爲:

接着我們來設置Activity的啓動模式只需要在AndroidManifest.xml裏對應的標籤設置Android:launchMode屬性,例如:

<activity  
android:name=".MainAcyivity"  
android:launchMode="standard" /> 

啓動模式解析:

(1)standard:

每次激活Activity時(startActivity),都創建Activity實例,並放入任務棧;
默認模式,可以不用寫配置。在這個模式下,都會默認創建一個新的實例。因此,在這種模式下,可以有多個相同的實例,也允許多個相同Activity疊加(記住,可以允許疊加,就代表可以重複創建此Activity)

示例如下圖:
假如我點擊了Activity1中的按鈕1和按鈕2(牛逼的人在瞬間同時點擊,暫不考慮後退的問題了):

(2)singleTop:

如果在任務的棧頂正好存在該Activity的實例, 就重用該實例,否者就會創建新的實例並放入棧頂(即使棧中已經存在該Activity實例,只要不在棧頂,都會創建實例)。
示例如下圖:

假如我點擊了Activity1中的按鈕1和按鈕2(牛逼的人在瞬間同時點擊,暫不考慮後退的問題了):這次點擊按鈕1,因爲棧頂存在Activity1,所以不會重複創建,如果不是棧頂,則會創建。

(3)singleTask:

如果在棧中已經有該Activity的實例,就重用該實例(會調用實例的onNewIntent())。重用時,會讓該實例回到棧頂,因此在它上面的實例將會被移除棧(銷燬)。如果棧中不存在該實例,將會創建新的實例放入棧中。

示例如下圖:

假如我點擊了Activity1中的按鈕1和按鈕2,又點了按鈕1(牛逼的人在瞬間順序點擊而不發生跳轉,暫不考慮後退的問題了):

(4)singleInstance:

在一個新棧中創建該Activity實例並讓多個應用共享該棧中的該Activity實例。一旦該模式的Activity的實例存在於某個棧中,任何應用再激活該Activity時都會重用該棧中的實例,其效果相當於多個應用程序共享一個應用,不管誰激活該Activity都會進入同一個應用中。

假如我點擊了Activity1中的按鈕1(只點擊了按鈕1)

啓動模式的實際應用場景

這四種模式中的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()獲取的一直都是老數據,根本無法接收跳轉時傳送的新數據!

根據上面啓動模式的介紹可得知,當CourseDetailActivity處於棧頂時,再次跳轉頁面到CourseDetailActivity時會直接複用原有的Activity,而且此頁面需要展示的數據是從getIntent()方法得來,可是initData()方法不會再次被調用,此時頁面就無法顯示新的數據。
當然這種情況系統早就爲我們想過了,這時我們需要另外一個回調 onNewIntent(Intent intent)方法,此方法會傳入最新的intent,這樣我們就可以解決上述問題。這裏建議的方法是重新去setIntent,然後重新去初始化數據和UI,代碼如下所示:

 @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        initData();
        initView();
    }

文章部分內容參考了《Android開發藝術探索》,後續傳上來。

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