欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android基礎(chǔ)總結(jié)篇之三:Activity的task相關(guān)介紹

 更新時間:2016年11月15日 10:21:49   作者:liuhe688  
這篇文章主要介紹了Android基礎(chǔ)總結(jié)篇之三:Activity的task相關(guān)介紹,具有一定的參考價值,有需要的可以了解一下。

本篇文章主要介紹了android基礎(chǔ)總結(jié)篇之三:Activity的task相關(guān),具有一定的參考價值,有需要的可以了解一下。

今天我們來講一下Activity的task相關(guān)內(nèi)容。

上次我們講到Activity的四種啟動模式的時候,已經(jīng)了解到一些關(guān)于task的技術(shù),今天我再向大家介紹一下。task是一個具有棧結(jié)構(gòu)的容器,可以放置多個Activity實例。啟動一個應(yīng)用,系統(tǒng)就會為之創(chuàng)建一個task,來放置根Activity;默認情況下,一個Activity啟動另一個Activity時,兩個Activity是放置在同一個task中的,后者被壓入前者所在的task棧,當用戶按下后退鍵,后者從task被彈出,前者又顯示在幕前,特別是啟動其他應(yīng)用中的Activity時,兩個Activity對用戶來說就好像是屬于同一個應(yīng)用;

系統(tǒng)task和task之間是互相獨立的,當我們運行一個應(yīng)用時,按下Home鍵回到主屏,啟動另一個應(yīng)用,這個過程中,之前的task被轉(zhuǎn)移到后臺,新的task被轉(zhuǎn)移到前臺,其根Activity也會顯示到幕前,過了一會之后,在此按下Home鍵回到主屏,再選擇之前的應(yīng)用,之前的task會被轉(zhuǎn)移到前臺,系統(tǒng)仍然保留著task內(nèi)的所有Activity實例,而那個新的task會被轉(zhuǎn)移到后臺,如果這時用戶再做后退等動作,就是針對該task內(nèi)部進行操作了。

我們今天就講一下和task相關(guān)的知識,主要分一下幾點:

1.Activity的affinity(親和力)

2.Intent幾種常見的flags

3.<activity>與task相關(guān)屬性

affinity:

affinity對于Activity來說就好像它的身份證一樣,可以告訴所在的task,自己屬于這個task中的一員;擁有相同affinity的多個Activity理論同屬于一個task,task自身的affinity決定于根Activity的affinity值。affinity在什么場合應(yīng)用呢?1.根據(jù)affinity重新為Activity選擇宿主task(與allowTaskReparenting屬性配合工作);2.啟動一個Activity過程中Intent使用了FLAG_ACTIVITY_NEW_TASK標記,根據(jù)affinity查找或創(chuàng)建一個新的具有對應(yīng)affinity的task。我們會在后面進行詳細講解。

默認情況下,一個應(yīng)用內(nèi)的所有Activity都具有相同的affinity,都是從Application(參考<application>的taskAffinity屬性)繼承而來,而Application默認的affinity是<manifest>中的包名,我們可以為<application>設(shè)置taskAffinity屬性值,這樣可以應(yīng)用到<application>下的所有<activity>,也可以單獨為某個Activity設(shè)置taskAffinity。例如:在系統(tǒng)自帶的Browser中,package為com.Android.browser,但是<application>卻自定義一個taskAffinity屬性值:

<application android:name="Browser" 
    android:label="@string/application_name" 
    android:icon="@drawable/ic_launcher_browser" 
    android:backupAgent=".BrowserBackupAgent" 
    android:taskAffinity="android.task.browser" > 

Intent幾種常見的flags:

在android.content.Intent中定義了若干個flags,其中最重要的有以下幾個:

1.FLAG_ACTIVITY_NEW_TASK:當Intent對象包含這個標記時,系統(tǒng)會尋找或創(chuàng)建一個新的task來放置目標Activity,尋找時依據(jù)目標Activity的taskAffinity屬性進行匹配,如果找到一個task的taskAffinity與之相同,就將目標Activity壓入此task中,如果查找無果,則創(chuàng)建一個新的task,并將該task的taskAffinity設(shè)置為目標Activity的taskActivity,將目標Activity放置于此task。注意,如果同一個應(yīng)用中Activity的taskAffinity都使用默認值或都設(shè)置相同值時,應(yīng)用內(nèi)的Activity之間的跳轉(zhuǎn)使用這個標記是沒有意義的,因為當前應(yīng)用task就是目標Activity最好的宿主。下面我們會通過實例進行演示這個特性:

我們新建兩個項目,分別命名為appA和appB,并且分別創(chuàng)建FirstActivity和SecondActivity,我們準備讓appB中的FirstActivity跳轉(zhuǎn)到appA的SecondActivity。appA中的SecondActivity配置如下:

<activity android:name=".SecondActivity"> 
   <intent-filter> 
    <action android:name="android.intent.action.APP_A_SECOND_ACTIVITY" /> 
    <category android:name="android.intent.category.DEFAULT" /> 
   </intent-filter> 
  </activity> 

然后,在appB中的FirstActivity跳轉(zhuǎn)代碼如下:

Intent intent = new Intent("android.intent.action.APP_A_SECOND_ACTIVITY"); 
startActivity(intent); 

我們要演示幾個步驟:1.在appB中的FirstActivity點擊按鈕跳轉(zhuǎn)到appA中的SecondActivity;2.按Home鍵回到主屏,在主選單中再次啟動appB;3.按Home鍵回到主屏,在主選單中啟動appA。演示過程如圖所示:



再次啟動appB應(yīng)用:

啟動appA應(yīng)用:

我們發(fā)現(xiàn)在從appB跳轉(zhuǎn)到appA的SecondActivity之后,SecondActivity實例好像是嵌入到了appB中,但是不影響appA的正常運行,這種關(guān)系如下圖所示:

然后我們修改一下跳轉(zhuǎn)的代碼:

Intent intent = new Intent("android.intent.action.APP_A_SECOND_ACTIVITY"); 
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
startActivity(intent); 

我們加上了FLAG_NEW_TASK標記,在來看一下演示結(jié)果:



再次啟動appB:

啟動appA:

我們看到差別了吧,當我們再次啟動appB時已經(jīng)看不到剛才啟動的appA中的SecondActivity,而啟動appA時卻直接看到了,說明這個SecondActivity實例并不在appB的task內(nèi),而是創(chuàng)建了一個task,這個task的affinity就是SecondActivity默認的affinity,由于appA的SecondActivity的affinity是從Application繼承而來,所以當appA啟動時會直接找到這個task,而不是創(chuàng)建新的task。我們看一下解析圖:

2.FLAG_ACTIVITY_CLEAR_TOP:當Intent對象包含這個標記時,如果在棧中發(fā)現(xiàn)存在Activity實例,則清空這個實例之上的Activity,使其處于棧頂。例如:我們的FirstActivity跳轉(zhuǎn)到SecondActivity,SecondActivity跳轉(zhuǎn)到ThirdActivity,而ThirdActivity又跳到SecondActivity,那么ThirdActivity實例將被彈出棧,使SecondActivity處于棧頂,顯示到幕前,棧內(nèi)只剩下FirstActivity和SecondActivity。這個SecondActivity既可以在onNewIntent()中接收到傳來的Intent,也可以把自己銷毀之后重新啟動來接受這個Intent。在使用默認的“standard”啟動模式下,如果沒有在Intent使用到FLAG_ACTIVITY_SINGLE_TOP標記,那么它將關(guān)閉后重建,如果使用了這個FLAG_ACTIVITY_SINGLE_TOP標記,則會使用已存在的實例;對于其他啟動模式,無需再使用FLAG_ACTIVITY_SINGLE_TOP,它都將使用已存在的實例,Intent會被傳遞到這個實例的onNewIntent()中。

下面我們來驗證一下這個過程:

首先,Activity啟動模式都按照默認值“standard”。從FirstActivity跳轉(zhuǎn)到SecondActivity,SecondActivity實例如下:
從ThirdActivity跳轉(zhuǎn)到SecondActivity時,跳轉(zhuǎn)代碼如下:

Intent intent = new Intent(this, SecondActivity.class); 
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
startActivity(intent); 

然后跳轉(zhuǎn)后SecondActivity實例如下:

從序列號可以看到這兩個實例是不同的,證明它是經(jīng)過了銷毀和重新的過程。

然后我們把ThirdActivity中的跳轉(zhuǎn)代碼添加FLAG_ACTIVITY_SINGLE_TOP標記:

Intent intent = new Intent(this, SecondActivity.class); 
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 
startActivity(intent); 

兩次實例均如下圖所示:

如果我們不想添加FLAG_ACTIVITY_SINGLE_TOP,那么把SecondActivity的啟動模式改為“standard”之外的三種即可,效果和上面一樣,都不會創(chuàng)建新的實例。

3.FLAG_ACTIVITY_SINGLE_TOP:當task中存在目標Activity實例并且位于棧的頂端時,不再創(chuàng)建一個新的,直接利用這個實例。我們在上邊的例子中也有講到。

4.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET:如果一個Intent中包含此屬性,則它轉(zhuǎn)向的那個Activity以及在那個Activity其上的所有Activity都會在task重置時被清除出task。當我們將一個后臺的task重新回到前臺時,系統(tǒng)會在特定情況下為這個動作附帶一個FLAG_ACTIVITY_RESET_TASK_IF_NEEDED標記,意味著必要時重置task,這時FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET就會生效。經(jīng)過測試發(fā)現(xiàn),對于一個處于后臺的應(yīng)用,如果在主選單點擊應(yīng)用,這個動作中含有FLAG_ACTIVITY_RESET_TASK_IF_NEEDED標記,長按Home鍵,然后點擊最近記錄,這個動作不含F(xiàn)LAG_ACTIVITY_RESET_TASK_IF_NEEDED標記,所以前者會清除,后者不會。關(guān)于這個標記,可以下圖示之:

這個標記對于應(yīng)用存在分割點的情況會非常有用。比如我們在應(yīng)用主界面要選擇一個圖片,然后我們啟動了圖片瀏覽界面,但是把這個應(yīng)用從后臺恢復(fù)到前臺時,為了避免讓用戶感到困惑,我們希望用戶仍然看到主界面,而不是圖片瀏覽界面,這個時候我們就要在轉(zhuǎn)到圖片瀏覽界面時的Intent中加入此標記。

5.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED:這個標記在以下情況下會生效:1.啟動Activity時創(chuàng)建新的task來放置Activity實例;2.已存在的task被放置于前臺。系統(tǒng)會根據(jù)affinity對指定的task進行重置操作,task會壓入某些Activity實例或移除某些Activity實例。我們結(jié)合上面的CLEAR_WHEN_TASK_RESET可以加深理解。

<activity>的task相關(guān)屬性

在<activity>中定義了幾個常見的task相關(guān)屬性,它們分別代表了task內(nèi)部不同的行為特征,我們就來逐個介紹一下:

1.android:allowTaskReparenting

這個屬性用來標記一個Activity實例在當前應(yīng)用退居后臺后,是否能從啟動它的那個task移動到有共同affinity的task,“true”表示可以移動,“false”表示它必須呆在當前應(yīng)用的task中,默認值為false。如果一個這個Activity的<activity>元素沒有設(shè)定此屬性,設(shè)定在<application>上的此屬性會對此Activity起作用。例如在一個應(yīng)用中要查看一個web頁面,在啟動系統(tǒng)瀏覽器Activity后,這個Activity實例和當前應(yīng)用處于同一個task,當我們的應(yīng)用退居后臺之后用戶再次從主選單中啟動應(yīng)用,此時這個Activity實例將會重新宿主到Browser應(yīng)用的task內(nèi),在我們的應(yīng)用中將不會再看到這個Activity實例,而如果此時啟動Browser應(yīng)用,就會發(fā)現(xiàn),第一個界面就是我們剛才打開的web頁面,證明了這個Activity實例確實是宿主到了Browser應(yīng)用的task內(nèi)。我們就來結(jié)合實例演示一下這個過程:

首先,在appB的FirstActivity中,我們將跳轉(zhuǎn)動作做以下改動:

Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com.hk")); 
startActivity(viewIntent); 

進入appB時的界面:

啟動web界面之后:

然后我們按Home鍵,是當前應(yīng)用退居后臺,我們回到主選單,重新啟動appB,界面如下:

此時我們在主選單中啟動Browser應(yīng)用,出現(xiàn)在我們眼前的界面是這樣的:

以上這種行為也證明了我們前面的論斷,為了更清楚的說明問題,也為了讓大家自己可以驗證,下面我們要再次演示一下appB和appA的啟動過程:

對于appA,在上面的基礎(chǔ)上,不用修改其他地方,只需為SecondActivity的<activity>元素添加一個屬性,如下:

<activity android:name=".SecondActivity" android:allowTaskReparenting="true"> 
... 
</activity> 

然后,在appB中的FirstActivity跳轉(zhuǎn)代碼改為:

Intent intent = new Intent("android.intent.action.APP_A_SECOND_ACTIVITY"); 
startActivity(intent); 

我們啟動appB,看到一下界面:

然后點擊按鈕,跳轉(zhuǎn)到appA中的SecondActivity,界面如下:

此時appB中的FirstActivity和appA中的SecondActivity處于同一個task中taskid為28,然后我們按下Home鍵,在主選單中再次啟動appB,我們發(fā)現(xiàn)appA的SecondActivity不見了,我們看到的是:

然后我們啟動appA,這是我們不會看到它的FirstActivity,而是看到了它的SecondActivity:
通常兩個應(yīng)用分別有自己的task,它們的taskid肯定不同,但這里的SecondActivity卻顯示taskid與appB相同,我們想一下也許就明白了,原來它是appB遷徙過來的,再啟動appA時并未生成任何新的Activity實例。這個時候如果我們按下后退鍵,appA就會立即退出,證明了此時appA的task里只有一個Activity實例,也就是這個SecondActivity實例。

需要注意的是,如果appB退居后臺之后,沒有再次啟動appB,而是直接啟動appA,將不會出現(xiàn)以上現(xiàn)象。重新宿主的動作發(fā)生在appB再次啟動的過程中。

android:allowReparenting的效果圖如下:

2.android:alwaysRetainTaskState

這個屬性用來標記應(yīng)用的task是否保持原來的狀態(tài),“true”表示總是保持,“false”表示不能夠保證,默認為“false”。此屬性只對task的根Activity起作用,其他的Activity都會被忽略。

默認情況下,如果一個應(yīng)用在后臺呆的太久例如30分鐘,用戶從主選單再次選擇該應(yīng)用時,系統(tǒng)就會對該應(yīng)用的task進行清理,除了根Activity,其他Activity都會被清除出棧,但是如果在根Activity中設(shè)置了此屬性之后,用戶再次啟動應(yīng)用時,仍然可以看到上一次操作的界面。

這個屬性對于一些應(yīng)用非常有用,例如Browser應(yīng)用程序,有很多狀態(tài),比如打開很多的tab,用戶不想丟失這些狀態(tài),使用這個屬性就極為恰當。

3.android:clearTaskOnLaunch

這個屬性用來標記是否從task清除除根Activity之外的所有的Activity,“true”表示清除,“false”表示不清除,默認為“false”。同樣,這個屬性也只對根Activity起作用,其他的Activity都會被忽略。

如果設(shè)置了這個屬性為“true”,每次用戶重新啟動這個應(yīng)用時,都只會看到根Activity,task中的其他Activity都會被清除出棧。如果我們的應(yīng)用中引用到了其他應(yīng)用的Activity,這些Activity設(shè)置了allowTaskReparenting屬性為“true”,則它們會被重新宿主到有共同affinity的task中。

無圖無真相,我們就來以實例演示一下這個過程,我們首先修改appB的根Activity的<activity>元素,如下:

<activity android:name=".FirstActivity" 
android:clearTaskOnLaunch="true"> 
... 
</activity> 

FristActivity界面如下:

然后我們讓FirstActivity跳轉(zhuǎn)到SecondActivity,結(jié)果如下:

然后我們按Home鍵回到主界面,再次啟動appB,我們看到以下結(jié)果:
我們看到,再次啟動appB時,我們只能看到FirstActivity界面,此時在FirstActivity之上的所有Activity都已經(jīng)被清除出棧。示意圖如下:

4.android:finishOnTaskLaunch

這個屬性和android:allowReparenting屬性相似,不同之處在于allowReparenting屬性是重新宿主到有共同affinity的task中,而finishOnTaskLaunch屬性是銷毀實例。如果這個屬性和android:allowReparenting都設(shè)定為“true”,則這個屬性勝出。

以上就是今天總結(jié)的內(nèi)容,這些都是常用的知識,除此之外還有很多等著我們?nèi)ヌ剿?,繼續(xù)努力。

原文鏈接:http://blog.csdn.net/liuhe688/article/details/6761337

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論