Activity的啟動模式詳解

飛天大豬發表於2016-08-18

Activity的啟動模式目前共有四種:standard、singleTop、singleTask和singleInstance。


(1)standard:標準模式,這也是系統的預設模式。使用該模式啟動Activity都會重新建立一個新的例項,不管這個例項在任務棧中是否已經存在。

  其實在這裡有一個坑,當我們用ApplicationContext去啟動standard模式的Activity的時候會報錯,錯誤如下:

  E/AndroidRuntime(674):android.util.AndroidRuntimeException:Calling startActivity from outside of onActivity context requires the FLAG_ACTIVITY_NEW_TASK flag.Is         this really what you want?

 這是因為standard模式的Activity預設會進入到啟動它的Activity所屬的任務棧中,但是非Activity型別的Context(如ApplicationContext)並沒有所謂的任務棧,所以就會丟擲這個異常。要解決這個問題也很簡單,那就是為待啟動的Activity指定FLAG_ACTIVITY_NEW_TASK 標記位,這樣就會建立一個新的任務棧,這個時候實際上是以singTask模式啟動的。

 (2)singLETop:棧頂複用模式。採用這種模式,當新啟動的Activity已經位於任務棧的棧頂,那麼就不會建立新的例項,而會複用棧頂的Activity,同時它的onNewIntent方法會被呼叫。這個新啟動的Activity的onCreate、onStart不會被系統呼叫,因為它並沒有發生改變。如果新啟動的Activity沒有不是位於棧頂,則會建立新的例項。

  Ex:假設有任務棧中為ABC,其中ABC分別為三個Activity,C位於棧頂。此時在啟動C(singTop模式),那麼棧內依然為ABC;如果啟動的是B(singTop),那麼就會變為ABCB。

(3)singleTask:棧內複用模式。這其實是一種單例模式,在這種模式下,只要Activity在任務棧中存在,那麼啟動Activity的時候都不會建立新的例項。當一個具有singTask的Activity啟動後(比如Activity A),系統首先會尋找是否存在A想要的任務棧,如果不存在,就會重新建立一個任務棧,然後建立A的例項並將A入棧。如果存在A所需的任務棧,這個時候就需要看A是否在棧中有例項,如果有,這複用A的例項,並會將A上面的所以例項移除棧。如果例項不存在,就建立A的例項併入棧。

 Ex:① 比如當前任務棧S1中的情況為ABC,這個時候Activity D以SingleTask啟動,其所需要的任務棧為S2,由於S2和D的例項都不存在,所以系統會先建立任務棧S2,然後在建立D的例項併入棧到S2。

          ②另一種情況,假設D所需的為S1棧,其他情況與上面的例子一樣,那麼由於S1已經存在,所以系統會直接建立D的例項併入棧到S1。

          ③如果D所需的任務棧為S1,S1的情況為ADBC,此時啟動D,系統就會將D切換至棧頂並呼叫onNewIntent方法。同時會將BC移除棧,所以最終S1裡的情況為AD。

(4)singleInstance:單例項模式。這是一種加強的singleTask模式,不僅具有singleTask的特性外,還加強了一點,那就是此模式的Activity只能單位位於一個任務棧。

那麼如何為Activity來指定啟動模式呢?

第一種方法:在AndroidMenifest中的Activity標籤下設定launchMode如




第二種方法:通過Intent設定Flag來為Activity 指定啟動模式



FLAG_ACTIVITY_NEW_TASK

這個標記位的作用是為Activity指定singleTask啟動模式,與在XML指定的效果相同


FLAG_ACTIVITY_SINGLE_TOP

這個標記位的作用是為Activity指定singleTop啟動模式,與在XML指定的效果相同


FLAG_ACTIVITY_CLEAR_TOP

具有此標記位的Activity,當它啟動時,在同一個任務棧中所以位於它上面的Activity都要出棧。這個標記位一般與FLAG_ACTIVITY_NEW_TASK一起出現,在這種情況下,被啟動的Activity例項如果已經存在,那麼系統會呼叫它的onNewIntent。如果被啟動的Activity採用standard模式啟動,那麼它連同它之上的Activity都要出棧,系統會建立新的Activity例項併入棧。


FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具有這個標記的Activity不會出現在歷史Activity的列表中。等同於XML中指定Activity的android:excludeFromRecents="true"



相關文章