1. 程式人生 > >android Activity 啟動模式 應用場景

android Activity 啟動模式 應用場景

棧的原理:先進後出,後進先出。所有操作都發生在棧頂。

首先介紹一下任務棧:

(1)程式開啟時就建立了一個任務棧, 用於儲存當前程式的activity,所有的activity屬於一個任務棧。 
(2)一個任務棧包含了一個activity的集合, 去有序的選擇哪一個activity和使用者進行互動:只有在任務棧棧頂的activity才可以跟使用者進行互動。 
(3)任務棧可以移動到後臺, 並且保留了每一個activity的狀態. 並且有序的給使用者列出它們的任務, 而且還不丟失它們狀態資訊。 
(4)退出應用程式時:當把所有的任務棧中所有的activity清除出棧時,任務棧會被銷燬,程式退出。

任務棧的缺點: 
(1)每開啟一次頁面都會在任務棧中新增一個Activity,而只有任務棧中的Activity全部清除出棧時,任務棧被銷燬,程式才會退出,這樣就造成了用,戶體驗差, 需要點選多次返回才可以把程式退出了。 
(2)每開啟一次頁面都會在任務棧中新增一個Activity還會造成資料冗餘, 重複資料太多, 會導致記憶體溢位的問題(OOM)。

為了解決任務棧的缺點,我們引入了啟動模式。

一 .standard - 正常模式(預設情況下,不設定LauchMode時)

誰啟動了該模式的Activity,該Activity就屬於啟動它的Activity的任務棧中。每次啟動一個Activity都會重新建立一個新的例項

二 .singleTop - 棧頂複用模式

分三種情況:

1.當前棧中已有該Activity的例項,並且位於棧頂。不會建立例項,而是複用棧頂的例項。回撥onNewIntent方法。

2.當前棧中已有該Activity的例項,但是不在棧頂。則會建立例項,其行為跟standard啟動模式一樣。

3.當前棧中不存在該Activity例項,其行為同standard啟動模式一樣。

上面兩種啟動模式都是在原任務棧中新建Activity例項,不會啟動新的Task,即使你指定了taskAffinity屬性(任務相關性)

taskAffinity:

⑴這個引數表示了一個Activity所需要任務棧的名字,預設情況下,所有Activity所需的任務棧的名字為應用的包名。

⑵我們可以單獨指定每一個Activity的taskAffinity屬性覆蓋預設值

⑶一個任務的affinity決定於這個任務的根activity(root activity)的taskAffinity

⑷在概念上,具有相同的affinity的activity(即設定了相同taskAffinity屬性的activity)屬於同一個任務

⑸為一個activity的taskAffinity設定一個空字串,表明這個activity不屬於任何task

三.singleTask - 棧內複用模式

啟動Activity時,首先根據taskAffinity去尋找當前是否存在一個對應名字的任務棧。

1.如果不存在,則會建立一個新的Task,並建立新的Activity例項入棧到新建立的Task中去。

2.如果存在,則得到該任務棧,查詢該任務棧中是否存在該Activity例項。

                     如果存在例項,則將它上面的Activity都出棧,然後回撥啟動的Activity例項的onNewIntent方法。

                     如果不存在該例項,則新建Activity,併入棧。

此外,我們可以將兩個不同App中的Activity設定為相同的taskAffinity,這樣雖然在不同的app中,但是Activity會分配到同一個Task中去。

四.singleInstance - 全域性唯一模式

該模式具備singleTask模式的所有特性外,與它的區別是:這種模式下的Activity會獨佔一個Task棧,具有全域性唯一性,即整個系統中就這麼一個例項,由於棧內複用的特性,後續的請求均不會建立新的Activity的例項,除非這個特殊的任務棧被銷燬了。以singleInstance模式啟動的Activity在整個系統中是單例的,如果在啟動這樣的Activity時,已經存在了一個例項,那麼會把他所在的任務排程到前臺,重用這個例項。

應用場景: 
singleTop適合接收通知啟動的內容顯示頁面。例如,某個新聞客戶端的新聞內容頁面,如果收到10個新聞推送,每次都開啟一個新聞內容頁面是很煩人的。

singleTask適合作為程式入口點。例如瀏覽器的主介面。不管從多少個應用啟動瀏覽器,只會啟動主介面一次,其餘情況都會走onNewIntent,並且會清空主介面上面的其他頁面。之前開啟過的頁面,開啟之前的頁面就ok,不再新建。

singleInstance適合需要與程式分離開的頁面。例如鬧鈴提醒,將鬧鈴提醒與鬧鈴設定分離。singleInstance不要用於中間頁面,如果用於中間頁面,跳轉會有問題,比如:A -> B (singleInstance) -> C,完全退出後,在此啟動,首先開啟的是B。

相信細心的同學已經看到onNewIntent這個方法了,接下來獻上小弟的拙見:

 大家遇到一個應用的Activity供多種方式呼叫啟動的情況,多個呼叫希望只有一個Activity的例項存在,這就需要Activity的onNewIntent(Intent intent)方法了。只要在Activity中加入自己的onNewIntent(intent)的實現加上Manifest中對Activity設定lanuchMode=“singleTask”就可以。

       onNewIntent()非常好用,Activity第一啟動的時候執行onCreate()---->onStart()---->onResume()等後續生命週期函式,也就時說第一次啟動Activity並不會執行到onNewIntent(). 而後面如果再有想啟動Activity的時候,那就是執行onNewIntent()---->onResart()------>onStart()----->onResume().  如果android系統由於記憶體不足把已存在Activity釋放掉了,那麼再次呼叫的時候會重新啟動Activity即執行onCreate()---->onStart()---->onResume()等。

     當呼叫到onNewIntent(intent)的時候,需要在onNewIntent() 中使用setIntent(intent)賦值給Activity的Intent.否則,後續的getIntent()都是得到老的Intent。