在一個項目中會包括着多個Activity,系統中使用任務棧來存儲建立的Activity實例,任務棧是一種「後進先出」的棧結構。舉個栗子,若咱們屢次啓動同一個Activity。系統會建立多個實例依次放入任務棧中。當按back鍵返回時,每按一次,一個Activity出棧,直到棧空爲止。當棧中無不論什麼Activity。系統就會回收此任務棧。android
上面這個樣例中的Activity並無設置啓動模式,你會發現屢次啓動同一個Activity。而系統卻建立了多個實例,白白浪費內存,這樣的狀況Android早就替咱們考慮好了。Android爲Activity 的建立提供了4種啓動模式,而依據實際應用場景的不一樣。爲Activity 選擇不一樣的啓動模式,最大化下降了每次都需要在棧中建立一個新的Activity的壓力,下降內存使用。設計模式
啓動模式的具體說明和使用場景?如下依據這篇博文來一一解惑。ide
說明: Android建立Activity時的默認模式,假設沒有爲Activity設置啓動模式的話,默以爲標準模式。每次啓動一個Activity都會又一次建立一個新的實例入棧,不管這個實例是否存在。學習
生命週期:如上所看到的,每次被建立的實例Activity 的生命週期符合典型狀況,它的onCreate、onStart、onResume都會被調用。spa
舉例:此時Activity 棧中以此有A、B、C三個Activity,此時C處於棧頂,啓動模式爲Standard 模式。設計
若在C Activity中加入點擊事件,需要跳轉到還有一個同類型的C Activity。結果是還有一個C Activity進入棧中,成爲棧頂。
code
說明:分兩種處理狀況:需要建立的Activity已經處於棧頂時,此時會直接複用棧頂的Activity。不會再建立新的Activity;若需要建立的Activity不處於棧頂,此時會又一次建立一個新的Activity入棧,同Standard模式同樣。xml
生命週期:若狀況一中棧頂的Activity被直接複用時,它的onCreate、onStart不會被系統調用,因爲它並無發生改變。但是一個新的方法 onNewIntent會被回調(Activity被正常建立時不會回調此方法)。生命週期
舉例:此時Activity 棧中以此有A、B、C三個Activity,此時C處於棧頂,啓動模式爲SingleTop 模式。狀況一:在C Activity中加入點擊事件,需要跳轉到還有一個同類型的C Activity。事件
結果是直接複用棧頂的C Activity。
狀況二:在C Activity中加入點擊事件,需要跳轉到還有一個A Activity。結果是建立一個新的Activity入棧。成爲棧頂。
說明:若需要建立的Activity已經處於棧中時,此時不會建立新的Activity,而是將存在棧中的Activity上面的其餘Activity全部銷燬,使它成爲棧頂。
生命週期:同SingleTop 模式中的狀況一一樣。僅僅會又一次回調Activity中的 onNewIntent方法
舉例:此時Activity 棧中以此有A、B、C三個Activity。此時C處於棧頂,啓動模式爲SingleTask 模式。
狀況一:在C Activity中加入點擊事件,需要跳轉到還有一個同類型的C Activity。結果是直接用棧頂的C Activity。狀況二:在C Activity中加入點擊事件,需要跳轉到還有一個A Activity。
結果是將A Activity上面的B、C全部銷燬,使A Activity成爲棧頂。
說明: SingleInstance比較特殊,是全局單例模式,是一種增強的SingleTask模式。它除了具備它全部特性外,還增強了一點:具備此模式的Activity僅僅能單獨位於一個任務棧中。
這個常用於系統中的應用,好比Launch、鎖屏鍵的應用等等,整個系統中僅僅有一個!因此在咱們的應用中通常不會用到。瞭解就能夠。
舉例:比方 A Activity是該模式,啓動A後。系統會爲它建立一個單獨的任務棧,因爲棧內複用的特性。興許的請求均不會建立新的Activity,除非這個獨特的任務棧被系統銷燬。
一種靜態的指定方法,在Manifest.xml文件裏聲明Activity的同一時候指定它的啓動模式,這樣在代碼中跳轉時會依照指定的模式來建立Activity。樣例例如如下:
<activity android:name="..activity.MultiportActivity" android:launchMode="singleTask"/>
一種動態的啓動模式,在new 一個Intent後,經過Intent的addFlags方法去動態指定一個啓動模式。樣例例如如下:
Intent intent = new Intent(); intent.setClass(context, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(intent);
注意:以上兩種方式都可以爲Activity指定啓動模式,但是兩者仍是有差異的。
(1)優先級:動態指定方式即另一種比第一種優先級要高,若二者同一時候存在,以另一種方式爲準。
(2)限定範圍:第一種方式沒法爲Activity直接指定 FLAG_ACTIVITY_CLEAR_TOP 標識,另一種方式沒法爲Activity指定 singleInstance 模式。
標記位既可以設定Activity的啓動模式,如同上面介紹的,在動態指定啓動模式,比方 FLAG_ACTIVITY_NEW_TASK 和 FLAG_ACTIVITY_SINGLE_TOP 等。它還可以影響Activity 的運行狀態 ,比方 FLAG_ACTIVITY_CLEAN_TOP 和 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 等。
如下介紹幾個基本的標記位,切勿死記,理解幾個就能夠,需要時再查官方文檔。
做用是爲Activity指定 「SingleTask」啓動模式。跟在AndroidMainfest.xml指定效果一樣。
做用是爲Activity指定 「SingleTop」啓動模式,跟在AndroidMainfest.xml指定效果一樣。
具備此標記位的Activity,啓動時會將與該Activity在同一任務棧的其餘Activity出棧。通常與SingleTask啓動模式一塊兒出現。它會完畢SingleTask的做用。但事實上SingleTask啓動模式默認具備此標記位的做用
具備此標記位的Activity不會出現在歷史Activity的列表中,使用場景:當某些狀況下咱們不但願用戶經過歷史列表回到Activity時,此標記位便體現了它的效果。它等同於在xml中指定Activity的屬性:
android:excludeFromRecents="trure"
這四種模式中的Standard模式是最普通的一種,沒有什麼特別注意。而SingleInstance模式是整個系統的單例模式,在咱們的應用中通常不會應用到。因此,這裏就具體解說 SingleTop 和 SingleTask模式的運用場景:
最多見的應用場景就是保持咱們應用開啓後僅僅有一個Activity的實例。最典型的樣例就是應用中展現的主頁(Home頁)。
假設用戶在主頁跳轉到其餘頁面,運行屢次操做後想返回到主頁,假設不使用SingleTask模式,在點擊返回的過程當中會屢次看到主頁,這明顯就是設計不合理了。
假設你在當前的Activity中又要啓動同類型的Activity,此時建議將此類型Activity的啓動模式指定爲SingleTop,可以下降Activity的建立,節省內存!
這裏還需要考慮一個Activity跳轉時攜帶頁面參數的問題。
因爲當一個Activity設置了SingleTop或者SingleTask模式後,跳轉此Activity出現複用原有Activity的狀況時,此Activity的onCreate方法將不會再次運行。onCreate方法僅僅會在第一次建立Activity時被運行。
而通常onCreate方法中會進行該頁面的數據初始化、UI初始化,假設頁面的展現數據無關頁面跳轉傳遞的參數,則沒必要操心此問題,若頁面展現的數據就是經過getInten() 方法來獲取,那麼問題就會出現:getInten()獲取的一直都是老數據,根本沒法接收跳轉時傳送的新數據!
如下,經過一個樣例來具體解釋:
Manifest.xml <activity android:name=".activity.CourseDetailActivity" android:launchMode="singleTop" android:screenOrientation="portrait" />
public class CourseDetailActivity extends BaseActivity{ ...... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_course_detail_layout); initData(); initView(); } //初始化數據 private void initData() { Intent intent = getIntent(); mCourseID = intent.getStringExtra(COURSE_ID); } //初始化UI private void initView() { ...... } ...... }
以上代碼中的CourseDetailActivity在配置文件裏設置了啓動模式是SingleTop模式,依據上面啓動模式的介紹可得知,當CourseDetailActivity處於棧頂時。再次跳轉頁面到CourseDetailActivity時會直接複用原有的Activity,而且此頁面需要展現的數據是從getIntent()方法得來,但是initData()方法不會再次被調用,此時頁面就沒法顯示新的數據。
固然這樣的狀況系統早就爲咱們想過了,這時咱們需要另一個回調 onNewIntent(Intent intent)方法。此方法會傳入最新的intent,這樣咱們就可以解決上述問題。這裏建議的方法是又一次去setIntent。而後又一次去初始化數據和UI。代碼例如如下所看到的:
/* * 複用Activity時的生命週期回調 */ @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); initData(); initView(); }
這樣,在一個頁面中可以反覆跳轉並顯示不一樣的內容。
啓動模式事實上是初學Android時會學到的知識點,曾經也是一知半懂,有些知識點事實上跟設計模式同樣,你不去使用而僅僅是學習並非可以掌握到精髓,僅僅有真正去使用纔會將這些變成你本身的,文章部份內容參考了《Android開發藝術探索》。好書推薦。
近期在使用啓動模式,特此來小小總結一番,網上關於此類的文章也有不少,但是多總結總結仍是故意無害的。