Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> activity 啟動模式

activity 啟動模式

編輯:關於Android編程

最近新參加的項目中使用到了activity的singleInstance 模式並在開發中產生了一些bug,發現組內的同事們對launchmode這件事情還缺少一些基本的認識。給大家講解的同時還是覺得可以把這個過程記錄下來,盡管是基礎部分很古老的知識但是很多開發者也還是沒有認真的學習過,即使已經熟悉了仔細想想也還會有些收獲的。一些基本概念的清晰理解在日常的開發也都有著意想不到的重要性。下面開始老生常談。

在AndroidMenifest.xml中每一個activity的launchMode可以有4種選項:standard,singleTop,singleTask,singleInstance。它們之間有很多區別,也有一些啟程轉接的東西。

standard,也是系統默認的方式。

每一次調用,系統都會創建一個新的activity然後他被置於當前發起intent的activity所在的task中的頂部。形式上可以這樣描述:

\

新開啟的#1 activity會統一位於當前task頂部與用戶交互,如果此時用戶關閉當前頁面按鈕會回到#0 activity。

 

在實際代碼的運行中我們可驗證這個過程,請看下面的dumpsys activity主要信息截圖:

\

同一個app中intent調用的發起方和響應方同處於一個task中,他們的先後關系也如前面圖示中描述的樣子。

 

同一個app中的調用場景是最常見的,那如果進行跨app的調用場景下又是個什麼樣子呢?請看下面dumpsys activity的主要信息截圖:

\

請注意紅色線框中的信息,兩個activity分屬不同的app中,通過intent的調用被排進了同一個task中與前面同一個app中是一致的,因此對於back按鈕的響應也與前述是一致的。

 

這裡面請注意ProcessRecord的信息與前面的截圖有著截然的區別,不同的ProcessRecord ID表明了2個activity分別運行於2個不同的process中。這裡確認了另一個重要的信息,android中task和process兩者間並沒有必然的關聯性。這樣設計也為誇app的信息傳送添加了一種方式。

 

下一個是 singleTop

 

它的基本操作過程與standart是一致的。關鍵的區別在於如果被調用的activity在task的頂部,那麼系統會繼續使用它並調用onNewIntent傳入新的intent信息。此時需要特別關注的是新的intent在調用onNewIntent後並不會自動與activity關聯,使用者必須自己調用setIntent()來建立這種關系。

 

這個過程圖示說明如下:

\

對於back按鈕的響應和面前的standard是一致的,這裡就不重復描述了。

 

在2次調用中dumpsys activity的主要信息是一致的,如下截圖:

\

 

singleTask

 

google的文檔中是這樣說明的“The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.”

 

相對於前面的類型這一個就比較復雜了,我們分幾步來詳細說明。

首先:第一次調用這個activity時,系統會將他單獨放入一個task中,然後將新的task切換到前台與用戶交互。當用戶關閉當前頁面,系統會將前台被調用的activity移出task,並將啟動他的task切換到前台。這個過程如下圖所示:

\

與singleTop相似的是,一旦activity被啟動後續所有的調用都會傳遞到到這個實例上,並將它所處的task切換到前台,而不會開啟新的實例。同時也有者顯著的區別,在task中如果activity沒有處於頂部那麼調用的時候它前面的activity都會被清除掉,以保證它位於頂部。如下圖所示:

\

 

通過分析描述為可以知道系統中這個activity只會被啟動一次,常駐於他啟動時所在的task並保持為根節點。

 

以上都是對文檔的理解,下面用實際的代碼檢驗一下理解的是否正確。

 

首先我們在app2中創建如下activity描述:

\

然後進行跨越app的調用,從app1中通過intent調用這個activity,這時dumpsys activity的主要信息截圖如下:

\

這裡可以清楚的看到系統在intent調用後創建了task#4527在其中安置了新啟動的MainActivity2,同時新建的task處於前台與用戶交互狀態。對back的響應也一如我們預期的那樣。

 

我們再驗證同一個app中調用的場景。操作步驟為啟動app2然後調用這個activity。此時dumpsys activity的主要信息截圖如下:

\

這時候可以看到並沒有創建新的task,啟動的activity也沒有被放到所處task的底部,此處系統的行為開始與文檔中描述的不符。再來嘗試跨越app的調用,啟動app1調用MainActivity2,此時dumpsys activity的主要信息截圖如下:

\

在這個截圖中我們發現了與文檔描述相似的地方,app1中發出的調用啟動的是前面已經打開過的activity,同時依然被放置於原先的task並沒有被加入app1的task。

 

接下來繼續驗證activity處於task下部時,被調用的場景。首先通過已經被啟動的MainActivity2調用其它activity,此時dumpsys activity的主要信息截圖如下:

\

然後從activity#1上調用MainActivity2,此時dumpsys activity的主要信息截圖如下:

\

系統將activity#1從task中移除,activity#0被置於task頂部與用戶進行交互。在此處終於與文檔中描述的完全一致了。

 

singleInstance

 

和前面的 “singleTask” 非常相似的作用,他們的區別主要有2個:第一被調用的activity一定會獨處於一個task中;第二這個activity會是task中唯一的一個activity。這個過程如下圖所示:

\

 

與 “singleTask”和 “singleInstance”相關的還有另外一個參數“taskAffinity”,它的存在對它們的行為有著很重要的影響。我們來看下它的效果。

首先從activity配置開始:

\

然後在同一個app中啟動MainActivity2,看一下dump sys activity的截圖信息:

\

這裡看到的信息和前面是完全一致的。但是設備中的截圖是這樣的:

\`

這樣的情況大多數同學都會很意外吧,同一個app,同一個ProcessRecord ID,在系統的任務管理裡面卻被列為2個單項?而且這兩個單項都是可以獨立關閉的。

在前面已經說明了,系統中process和task是分開管理的並沒有必然的聯系。在這裡我們更進一步可以發現系統的任務管理是基於task的而非基於process,當我們在手機上通過系統的任務管理器關閉一個項目的時候,實際上系統關閉的是一個task,而並不是直接作用於一個process。這樣的情況可能和大部分人心中的認知是不符的。關於系統對task和process管理將會在後面的文章裡介紹。

特別說明一下,文章裡的測試結果~截圖~dump信息都是在google官方的模擬器和原生的5.0系統中獲取的,其他第三方系統或多或少在行為和顯示上都會有一些區別,具體機型還需要具體測試。

在這次的介紹裡面我最想表達給讀者的是3個關鍵點:

第一:關於學習,務必主要基於官方的文檔和說明。在我自己學習的過程中驗證過很多網絡上文章中的內容,可以發現其中有很多錯誤的信息,也有很多文章幾經轉載與原文已經有很大的出入了。

第二:學習的過程中務必要加入自己的實踐操作,將各種相關的工具結合起來驗證,前面的檢驗中已經發現了即使官方的文檔中也可能有一些不是很精確的內容。特別是對於android這樣的開源系統,經過各個廠商的定制它們的產品在一些細節的地方系統行為也是各有不同的,沒有經過實際的驗證很可能會發現一些意外的情況。

第三:細節。所有的學習務必要關注細節,對細節的關注不足很可能導致在認知上與實際情況產生偏差。

心心相念,必有回響。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved