android基礎知識05:四大組件之activity 03

來源:互聯網
上載者:User

 本系列開始介紹activity的四大組件,主要是整理網路上關於這一部分的相關資料。包含如下三篇文章:

        android基礎知識05:四大組件之activity 01:基礎知識

       android基礎知識05:四大組件之activity 02:activity與task

       android基礎知識05:四大組件之activity 03:啟動模式執行個體

         

通過上一篇的博文介紹,大家應該對activity有個比較直觀的認識。

        本文將繼續介紹activity與task的關係。

        本文主要來自博文:《Android四種Activity的載入模式》《Android Activity LaunchMode 驗證》《Android的七巧板Activity之二
Activity的載入模式》

1、Activity棧
        上面提到開發人員是無法控制Activity的狀態的,那Activity的狀態又是按照何種邏輯來運作的呢?這就要知道 Activity 棧。
        每個Activity的狀態是由它在Activity棧(是一個後進先出LIFO,包含所有正在運行Activity的隊列)中的位置決定的。
        當一個新的Activity啟動時,當前的活動的Activity將會移到Activity棧的頂部。
        如果使用者使用後退按鈕返回的話,或者前台的Activity結束,在棧上的Activity將會移上來並變為活動狀態。如所示:

        一個應用程式的優先順序是受最高優先順序的Activity影響的。當決定某個應用程式是否要終結去釋放資源,Android記憶體管理使用棧來決定基於Activity的應用程式的優先順序。
2、Activity狀態 
        一般認為Activity有以下四種狀態:
        活動的:當一個Activity在棧頂,它是可視的、有焦點、可接受使用者輸入的。Android試圖盡最大可能保持它活動狀態,殺死其它Activity來確保當前活動Activity有足夠的資源可使用。當另外一個Activity被啟用,這個將會被暫停。 
        暫停:在很多情況下,你的Activity可視但是它沒有焦點,換句話說它被暫停了。有可能原因是一個透明或者非全屏的Activity被啟用。 
        當被暫停,一個Activity仍會當成活動狀態,只不過是不可以接受使用者輸入。在極特殊的情況下,Android將會殺死一個暫停Activity來為活動的Activity提供充足的資源。當一個Activity變為完全隱藏,它將會變成停止。 
        停止:當一個Activity不是可視的,它“停止”了。這個Activity將仍然在記憶體中儲存它所有的狀態和會員資訊。儘管如此,當其它地方需要記憶體時,它將是最有可能被釋放資源的。當一個Activity停止後,一個很重要的步驟是要儲存資料和當前UI狀態。一旦一個Activity退出或關閉了,它將變為待用狀態。 
        待用: 在一個Activity被殺死後和被裝在前,它是待用狀態的。待用Acitivity被移除Activity棧,並且需要在顯示和可用之前重新啟動它。

3、activity的四種載入模式
        在android的多activity開發中,activity之間的跳轉可能需要有多種方式,有時是普通的產生一個新執行個體,有時希望跳轉到原來某個activity執行個體,而不是產生大量的重複的activity。載入模式便是決定以哪種方式啟動一個跳轉到原來某個Activity執行個體。
        在android裡,有4種activity的啟動模式,分別為: 
                standard: 標準模式,一調用startActivity()方法就會產生一個新的執行個體。
                singleTop: 如果已經有一個執行個體位於Activity棧的頂部時,就不產生新的執行個體,而只是調用Activity中的newInstance()方法。如果不位於棧頂,會產生一個新的執行個體。
                singleTask: 會在一個新的task中產生這個執行個體,以後每次調用都會使用這個,不會去產生新的執行個體了。
                singleInstance: 這個跟singleTask基本上是一樣,只有一個區別:在這個模式下的Activity執行個體所處的task中,只能有這個activity執行個體,不能有其他的執行個體。
        這些啟動模式可以在功能資訊清單檔AndroidManifest.xml中進行設定,<activity>中的launchMode屬性。
        相關的代碼中也有一些標誌可以使用,比如我們想只啟用一個執行個體,則可以使用 Intent.FLAG_ACTIVITY_REORDER_TO_FRONT 標誌,這個標誌表示:如果這個activity已經啟動了,就不產生新的activity,而只是把這個activity執行個體加到棧頂來就可以了。
Intent intent = new Intent(ReorderFour.this, ReorderTwo.class);  
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);  
startActivity(intent);  
        Activity的載入模式受啟動Activity的Intent對象中設定的Flag和manifest檔案中Activity的<activity>元素的特性值互動控制。
下面是影響載入模式的一些特性
        核心的Intent Flag有: 
FLAG_ACTIVITY_NEW_TASK 
FLAG_ACTIVITY_CLEAR_TOP 
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 
FLAG_ACTIVITY_SINGLE_TOP 
        核心的<activity>特性有: 
taskAffinity 
launchMode 
allowTaskReparenting 
clearTaskOnLaunch 
alwaysRetainTaskState 
finishOnTaskLaunch

4、四種載入模式的區別
1)所屬task的區別

        一般情況下,“standard”和”singleTop”的activity的目標task,和收到的Intent的寄件者在同一個task內,就相當於誰調用它,它就跟誰在同一個Task中。
        除非Intent包括參數FLAG_ACTIVITY_NEW_TASK。如果提供了FLAG_ACTIVITY_NEW_TASK參數,會啟動到別的task裡。 
        “singleTask”和”singleInstance” 總是把要啟動的activity作為一個task的根項目,他們不會被啟動到一個其他task裡。
2)是否允許多個執行個體
        “standard”和”singleTop”可以被執行個體化多次,並且是可以存在於不同的task中;這種執行個體化時一個task可以包括一個activity的多個執行個體; 
        “singleTask”和”singleInstance”則限制只產生一個執行個體,並且是task的根項目。 
        singleTop 要求如果建立intent的時候棧頂已經有要建立的Activity的執行個體,則將intent發送給該執行個體,而不建立新的執行個體。
3)是否允許其它activity存在於本task內
        “singleInstance”獨佔一個task,其它activity不能存在那個task裡;
        如果它啟動了一個新的activity,不管新的activity的launch mode 如何,新的activity都將會到別的task裡運行(如同加了FLAG_ACTIVITY_NEW_TASK參數)。 
        而另外三種模式,則可以和其它activity共存。
4)是否每次都產生新執行個體
        “standard”對於每一個啟動Intent都會產生一個activity的新執行個體; 
“singleTop”的activity如果在task的棧頂的話,則不產生新的該activity的執行個體,直接使用棧頂的執行個體,否則,產生該activity的執行個體。
        比如:
        現在task棧元素為A-B-C-D(D在棧頂),這時候給D發一個啟動intent,如果D是 “standard”的,則產生D的一個新執行個體,棧變為A-B-C-D-D。 
        如果D是singleTop的話,則不會生產D的新執行個體,棧狀態仍為A-B-C-D 
        如果這時候給B發Intent的話,不管B的launchmode是”standard” 還是 “singleTop” ,都會產生B的新執行個體,棧狀態變為A-B-C-D-B。
        “singleInstance”是其所在棧的唯一activity,它會每次都被重用。
        “singleTask”  如果在棧頂,則接受intent,否則,該intent會被丟棄,但是該task仍會回到前台。 當已經存在的activity執行個體處理新的intent時候,會調用onNewIntent()方法,如果收到intent產生一個activity執行個體,那麼使用者可以通過back鍵回到上一個狀態;如果是已經存在的一個activity來處理這個intent的話,使用者不能通過按back鍵返回到這之前的狀態。

5、Android Activity LaunchMode 驗證

       在Android中,每個Activity有4種LaunchMode,預設是standard,下面對這四種模式進行執行個體驗證加深理解。 
       設計兩個Activity,分別稱為A,B,每個Activity上面都放置兩個按鈕,一個啟動A,一個啟動B。 
       介面如下:(上面的一行文字用來識別是在A介面還是在B介面) 

在代碼中實現onCreate(): 

Button btnA = (Button)findViewById(R.id.btnA);          btnA.setOnClickListener(new OnClickListener() {                       public void onClick(View v) {                  // TODO Auto-generated method stub                  startActivity(new Intent(A.this, A.class));              }          });                    Button btnB = (Button)findViewById(R.id.btnB);          btnB.setOnClickListener(new OnClickListener() {                       public void onClick(View v) {                  // TODO Auto-generated method stub                  startActivity(new Intent(A.this, B.class));              }          });                    Log.e("Task:"+getTaskId(), "A" + mId + " created.");   

onNewIntent():

Log.e("Task:"+getTaskId(), "A" + mId + " onNewIntent.");  

onDestroy():

Log.e("Task:"+getTaskId(), "A" + mId + " destroyed.");  

這樣就可以直觀的從Logcat輸出中看到Activity的建立、銷毀以及請求的響應。 

1.兩個Actiity的LaunchMode都為預設的standard,啟動Ap,看到輸出: 
Task:9(380): A1 created. 
A被建立了一個執行個體A1,並且放在了任務9中。 
此時任務棧中內容為: 

點擊介面上啟動A的按鈕,看到輸出: 
Task:9(380): A2 created. 
A再次被建立了一個新的執行個體A2,仍然放在任務9中。 
此時任務棧中內容為: 
AA
點擊啟動B的按鈕, 
Task:9(380): B1 created. 
B被建立一個新的執行個體B1,仍然放在任務9中。 
此時任務棧內容為: 
AAB 
再啟動B, 
Task:9(380): B2 created. 
B又被建立了一個新的執行個體B2,仍然在任務9中。 
任務棧內容為: 
AABB 
按Back鍵依次返回案頭,輸出依次為: 
Task:9(380): B2 destroyed. 
Task:9(380): B1 destroyed. 
Task:9(380): A2 destroyed. 
Task:9(380): A1 destroyed. 
任務棧的變化次序為: 
AABB 
AAB 
AA 

結論: 
每個Intent,都建立了一個新的Activity來響應,並且Back時是按照彈棧的順序處理的。 

2.B設定為SingleTop,啟動Ap: 
Task:10(409): A1 created. 
再啟動A: 
Task:10(409): A2 created. 
再啟動B: 
Task:10(409): B1 created. 
再啟動B: 
Task:10(409): B1 onNewIntent. 
結論: 
當B不在棧頂時,仍然會建立B的新執行個體。 
當B在棧頂時,請求啟動B的Intent並沒有觸發建立B的新執行個體,而是觸發了棧頂B的onNewIntent() 
按Back鍵依次返回案頭,輸出依次為: 
Task:10(409): B1 destroyed. 
Task:10(409): A2 destroyed. 
Task:10(409): A1 destroyed. 
結論: 
雖然發送了四次Intent,但實際上只建立了3個Activity,所以只有3次銷毀輸出。 

3.B設定為SingleTask,啟動Ap: 
Task:11(438): A1 created. 
啟動B: 
Task:11(438): B1 created. 
啟動A: 
Task:11(438): A2 created. 
啟動B: 
Task:11(438): B1 onNewIntent. 
Task:11(438): A2 destroyed. 
結論: 
當B已經存在時,再次請求B會觸發已經存在的B1執行個體的onNewIntent; 
並且如果B所在的任務棧上面有其他Activity,那麼其他Activity會被銷毀。 

4.B設定為SingleInstance,啟動Ap: 
Task:12(466): A1 created. 
啟動B,此時新建立了任務棧13,和先前的A1並不在一個任務。 
Task:13(466): B1 created. 
再啟動B,沒有建立新執行個體: 
Task:13(466): B1 onNewIntent. 
再啟動A,再舊的任務12中建立了A的新執行個體 
Task:12(466): A2 created. 
按下Back鍵: 
Task:12(466): A2 destroyed. 
看輸出和前面沒區別,但是注意介面,此時不是切換到B介面,因為此時活動任務是12,所以A1被顯示了出來。 
再次按下Back鍵: 
Task:12(466): A1 destroyed. 
此時因為任務12已經結束,B1所在的任務13成為活動任務,B1的介面才被顯示出來。  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.