Android中的啟動模式(下)

來源:互聯網
上載者:User

標籤:

在這篇文章中,我會繼續跟大家分享有關於Android中啟動模式的相關知識。當然,如果對這個啟動模式還不完全瞭解或者沒有聽過的話,可以先看看我之前寫的有關於這個知識點的入門篇Android的啟動模式(上)。好了,言歸正傳,在上一篇已經介紹過,activity在棧中預設不能重排,因此,應用中的一個activity可能被多次執行個體化並且壓入同一個棧中,:

如果此時使用back鍵返回,activity的每個執行個體都將會按照開啟的順序重新出現。這勢必會導致使用者生體驗效果,因此要改變這種現象或者解決上篇末尾提到的問題,對啟動模式的瞭解必不可少,當然,若想瞭解得更加透徹的話,歡迎訪問官方文檔:Tasks and Back Stack。

定義啟動模式

總的來說,啟動模式決定了你的activity和task的關聯性。當一個activity啟動的時候,有兩種方式指定它與task的關聯:使用manifest檔案和使用intent flag。當intent的flag和manifest所指定的啟動模式發生衝突的時候,此時就以intent flag指定的模式為準。

  1. 使用manifest資訊清單檔設定啟動模式

    通過在manifest檔案中添加launchMode屬性來指定啟動模式:

    • standard,預設的LaunchMode,也是最容易理解的。如果某個Activity使用該 LaunchMode, 當這個Activity啟動時,系統會建立一個該Activity的新的執行個體,並且傳遞 一個intent給它。該 Activity可以被執行個體化多次,各個執行個體可以屬於不同的Task,一個Task 中也可以存在多個執行個體。

    • singleTop,如果這個Activity有一個執行個體已經存在於當前Task的頂部,那麼系統就會傳 遞一 個intent給這個執行個體的onNewIntent()方法,而不會去重新建立一個新的Activity執行個體。 這個 Activity也可以被執行個體化多次,每個執行個體可以屬於不同的task,但只有當Back Stack棧頂 的Activity執行個體不是該Activity的執行個體時,一個task中也可以存在多個執行個體。應該注意的是,
      當一個Activity的新執行個體建立完畢後,使用者可以按返回鍵返回前一個activity。但是當 Activity已有執行個體正在處理剛到達的intent時,使用者無法用返回鍵回到onNewIntent()中 intent到來之前的Activity 狀態。

    • singleTask,系統建立一個新的Task,並且執行個體化這個Activity作為這個Task的根 Activity。然而,若這個Activity已經存在了一個執行個體在一個Task中,那麼系統就會將這個 Intent傳遞到這個Activity的onNewIntent()方法,而不是去重新建立一個執行個體。同一個時 間,只允許存在一個這樣的Activity。注意的是,雖然系統建立了一個新的Task,但是只要按 下返回鍵還是會回到原來的Activity

    • singleInstance,和"singleTask"類似,不同的是,系統不會再該activity執行個體的task中,啟動任何其他Activity到這個task中。這個Activity是它所在的task中唯一的成員。任何有這個activity啟動的Activity都會放入到另外一個task中。

對於返回處理,不管activity是在一個新的task啟動,還是在當前task中啟動,只要一按下返回鍵,就會返回到之前的那個activity中。但是也是存在一種情況例外,就是當你啟動一個啟動模式設為singleTask的Activity時,如果這個activity在一個後台task中存在執行個體,那個這整個task將會被放置到前台,這時候,back stack就會包含這個task中所有的activities,並且它們都是放在棧頂。如:

  1. 使用Intent的flag設定啟動模式

    當你啟動一個Activity時,你也可以動態設定intent的flag,然後通過startActivity()方法啟動activity,從而修改其啟動的activity與它的task的關聯模式。具體可以使用的flag有:

    • FLAG_ACTIVITY_NEW_TASK:對應之前的“singleTask”,在新的task中啟動activity,如果一個你需要的activity的task已經存在,則將它推向前台,恢複其上一個狀態,它通過onNewIntent()收到這個新的intent。

    • FLAG_ACTIVITY_SINGLE_TOP:對應之前的“singleTop”,如果被啟動的activity是當前頂部的activity,則已經存在的執行個體會收到onIntent(),而不會重新去建立這個執行個體。

    • FLAG_ACTIVITY_CLEAR_TOP:這個行為在launchMode屬性中沒對應的屬性值,若被啟動的activity已經在當前task中運行,則不會建立它的新執行個體,而是的銷毀在它之上的其他所有的activities,然後通過 onNewIntent()傳遞一個新的intent給這個恢複了的activity,它一般會與FLAG_ACTIVITY_NEW_TASK一起使用。值得注意的是,如果activity的啟動模式是"standard",它自己也將被移除,然後一個新的執行個體將被啟動。這是因為當啟動模式是"standard"時,為了接收新的intent必須建立新的執行個體

任務共用性的處理(Handling affinities)

一般來說,singleTask就是開啟一個新的Task,但是在實際使用過程中,我們有時會發現,有時候並不是這樣的,這是因為我們定義了affinities,也就是任務公用性。

affinity定義了一個Activity將被分配到哪一個Task中。預設情況下,同一個app中得所有activity有一個同樣的affinity,因此,預設情況下同一個應用程式中得所有activity都在同一個task中。一個Task的affinity由這個Task的根Actiivty決定。然而,我們可以修改Activity預設的affinity,這樣,不同應用程式的Activity可以共用同樣的affinity,或者同一個程式的不同Activity分配不同的affinity。一個應用程式預設的affinity就是應用程式的包名,所以,如果我們想定義一個不同的affinity,必須和預設的affinity不同。我們可以通過中得android:taskAffinity修改整個程式的affinity,也可以通過的android:taskAffinity對單個Activity的affinity修改。

而affinity的使用通常有以下兩種情況,

  1. 當android:launchMode是singleTask或者Intent中包含FLAG_ACTIVITY_NEW_TASK:

    預設情況下,我們調用startActivity(),會執行個體化一個Activity,放入到與調用者相同的task。但是如果這個Activity的的啟動模式是singleTask,或者啟動它的Intent包含了
    FLAG_ACTIVITY_NEW_TASK時,系統會進行如下的步驟:

    • 判斷這個Activity有沒有執行個體已經存在了,有的話,直接傳遞Intent到它的onNewIntent()方法中。
    • 如果不存在,系統尋找是否有與這個Activity相同affinity的Task已經存在,如果存在,那麼就將這個Activity啟動到這個Task中。
    • 如果不存在這樣的Task,那麼系統就會建立一個新的Task,並且將這個Activity啟動這個Task中,作為根Activity。

    因此,從現在看來,只是單純的用singleTask指定Activity,是不能開闢一個新的Task的,因為我們並沒有給他指定affinity。而官方文檔對於singleTask的描述,都是基於我們使用了不同的affinity的前提下,只不過是省略了這個描述。所以,我們要明白,singleTask的正確用法,應該是結合affinity使用的。

  2. 當一個Activity設定allowTaskReparenting屬性為true:

    這個屬性定義了一個Activity,表示是否可以從一個啟動它的task,切換到與它相同affinity的task中裡去(當這個task切換到前台的時候)。true表示可以移動,false表示它必須呆在啟動他得task裡。
    通常情況下,當一個Activity啟動了,那麼它就會存在於啟動它的task中,並且在整個生命週期中都留在這個task中。但是,我們可以通過這個屬性,做出如下改變,當這個Activity當前的Task處於後台,這個時候如果有一個該Activity具有相同affinity的Task被啟動到前台,那麼這個Activity就可以從它之前的Task,移動到這個新的Task顯示。
    通常,它的作用是將app中得Activity與app的main task結合起來,舉個例子,如下:
    有一個e-mail程式,他需要呼叫瀏覽器程式的某個Activity(假設為Activity A)來顯示一些資料,這個Activity A的該屬性設定為true。現在,e-mail程式調用了這個Activity A,在使用者看來,好像這個Activity A就是e-mial程式的一部分,因為這個Activity A和這個e-mail程式在同一個task中。現在將e-mail退出到後台,啟動瀏覽器程式,因為Activity A和瀏覽器程式有相同的affinity,所以Activity A從e-mail程式的Task移動到瀏覽器程式的Task,並顯示在前台。當我們下次再啟動e-mail程式時,Activity A就不會存在,因為他已經移動到瀏覽器程式的Task裡去了。

清理Back Stack

如果使用者離開一個task很久,系統就會清理這個task中除了根activity之外的所有activities。當使用者返回到這個task,只有根activity會被恢複。但是我們可以設定一些activity的屬性,用來改變這一行為:

  • alwaysRetainTaskState

    如果這個屬性在task的根activity中被設定為true,那麼上面描述的預設行為不會發生,即便過了很長時間,task仍將會保持所有的activities。

  • clearTaskOnLaunch

    如果這個屬性在task的根activity中被設定為true,每次使用者離開這個task,整個task都會被清到只剩根activity,這樣使用者只會永遠返回到它最初的狀態,即便離開的時間很短。

  • finishOnTaskLaunch

    這個屬性和上一個很像,不同的是,它只作用於單個activity,而不是整個task。它可以引起任何activity離開,包括根activity。當它被設定為true時,這個activity只在當前會話中屬於這個task,如果使用者離開後再返回,它也不會再出現。

開啟一個Task

我們可以通過一個Activity指定一個intent過濾器,如下面:

<activity ...><intent-filter ... >   <action android:name="android.intent.action.MAIN" />   <category android:name="android.inp tent.category.LAUNCHER" />   </intent-filter>...</activity>

這時這個activity就作為根activity存在於一個task中,這個activity也是進入這個task的進入點,同時,它的表徵圖和標籤也會被顯示在應用啟動介面上,這時使用者就可以啟動這個activity並且再次回到這個任務。因此,從這裡我們可以看到,要使用“singleTask”與“singleInstance”,就必須這個activity應當也有ACTION_MAIN與CATEGORY_LAUNCHER過濾器。因為假如沒有設定這兩個過濾器的話,當一個intent啟動一個"singleTask"的activity,在新的Task中進行初使化,運行一段時間後,使用者突然按上了home鍵回到案頭,此時這個Task就被移到後台並且不可見,因為這個activity沒有設定過濾器,所以不是應用啟動的activity,那麼使用者也就無法返回到這個Task中了。

總結

今天的分享也差不多接近尾聲了,有關Android的啟動模式的主要部分的分析也大多涉及到了。我想,如果大家想要全面地瞭解Android的啟動模式的話,我希望可以堅持看完這兩篇文章,我相信,看完後你對Android的啟動模式還有工作棧的理解應該有了很大的提高,對activity與Task的操作也會更加得心應手。當然,如果你覺得文章中有什麼寫得錯誤或者不瞭解的地方,歡迎留言交流,謝謝!

 

  

Android中的啟動模式(下)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.