Activity的啓動模式和常見Flag組合

衆所周知,Activity是Android四大組件之一,且應是初級程序員最先接觸使用的Android技術,當然也會較早知道Activity有四種啓動模式,但是可能對其瞭解不深,即使部分幾年工作經驗的開發由於業務方向等也不一定清楚其原理。
首先,要明確,Android爲何要給Acitivity設計這個東西呢。我們程序開發在學習數據結構時都學過形形色色的數據結構,不同的數據結構都有不同的優缺點,和適用場景。而且後講的數據結構基本是爲了解決前邊數據結構的部分缺點而設計的。首先樹立一個觀念,Android中的設計都是爲了適用特定使用場景或解決某種問題,或者說效率問題或者空間問題而設計的,所以清楚的瞭解其原理和優缺點,對我們的開發有很大的促進作用。
任務棧,是一種“後進先出”的棧結構。

四種啓動模式

1)Standard:標準模式,默認啓動模式,每次啓動一個activity都會重新創建一個新實例,不管是否已有實例。即使從ActivityA startActivity ActivityA,也會再次創建A的實例放於棧頂,當回退時,回到上一個ActivityA的實例。
此模式是一種多實例實現方式,一個任務棧可以有多個實例,每個實例也可以屬於不同的任務棧。誰啓動了這個Activity,那麼其就運行在啓動它的那個Activity所在的棧中。而正因爲如此,如果我們使用ApplicationContext去啓動standard模式的Activity時必須要帶FLAG_ACTIVITY_NEW_TASK的flag,由於使用application context非Activity類型的context,就沒有任務棧,所以需要增加那個flag標記,意思是創建一個新的任務棧。

2)SingleTop:棧頂複用模式。如果新Activity已經位於任務棧的棧頂,那麼此Activity則不會被重新創建,同時會回調onNewIntent方法,但是其onCreate,onStart不會被調用,因爲未發生改變。即不會走onCreate->onStart,會直接進入ActivityonPause->onNewIntent->onResume 方法但是如果新Activity實例不在棧頂,則還會重新創建,此時又類同於standard會重新創建實例。
3)SingleTask:棧內複用方式。如果棧中存在此Activity實例,多次啓動此Activity實例不會創建新的實例,棧內在此實例之上的Activity都會出棧(clear top效果),直到當前Activity到達棧頂,並執行onNewIntent方法。如果棧中不存在此Activity實例,則重新創建並壓入棧中。
4)SingleInstance:單實例模式,其具有singleTask的所有特點並且此模式只能單獨位於一個任務棧中。整個Android操作系統中最多隻有一個該Activity實例存在,如果task中存在實例,執行其onNewIntent方法。

指定啓動模式方式


第一種方法: 通過AndroidMenifest.xml指定。

<activity android:name=".activity.MainActivity" android:launchMode="singleTask"/>

第二種方法:

Intent intent = new Intent();
intent.setClass(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
二者的區別是,
1.第二種方法的優先級高於第一種,兩種同時存在時,則以第二種爲準。
2.限定範圍不同,第一種無法直接爲Activity設定FLAG_ACTIVITY_CLEAR_TOP標識,而第二種方式無法爲Activity指定singleInstance模式。

筆者曾在這裏走過坑,開始不知道兩種設置是互斥有優先級的,一直在懷疑爲何xml裏設置的模式不管用,其實由於啓動時有New_task的flag,,已經確定爲singletask的模式了,而且還加了FLAG_ACTIVITY_CLEAR_TASK(當時對此只看字面不理解)。且由於設置了透明主題背景,在onpause中判斷爲界面已消失(其實onpause不代表界面不可見),此時還未進入onstop,又要啓動時,此Activity會重新創建。
即ActivityA的上一個實例進入了onpause,還未onStop, 又啓動一個新的ActivityA實例,由於clear_task標記的存在,會銷燬當前棧,oncreate-onstart-onresume, 然後上一個實例進入onstop,在這個onstop中又釋放了一些資源,導致問題。後來不得不檢測是否是最新實例,才釋放資源。

Activity的Flag

FLAG_ACTIVITY_NEW_TASK
同XML中指定爲singleTask模式

FLAG_ACTIVITY_SINGLE_TOP
同XML中指定爲singleTop模式
FLAG_ACTIVITY_CLEAR_TOP
當具有此標記的activity啓動時,同一個任務棧上所有的Activity都要出棧。一般和singleTasK模式一起出現。如實例存在,調用onNewIntent。singleTask默認就有此標記的效果。
FLAG_ACTIVITY_CLEAR_TASK
該模式必須配合FLAG_ACTIVITY_NEW_TASK一起使用,效果就是:
**如果目標task已經存在,將清空已存在的目標Task,否則,新建一個Task棧,之後,新建一個Activity作爲根Activity。**Intent.FLAG_ACTIVITY_CLEAR_TASK的優先級最高,基本可以無視所有的配置,包括啓動模式及Intent Flag,哪怕是singleInstance也會被finish,並重建。

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