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

LocalActivityManager

編輯:關於Android編程

1.LocalActivityManager的說明

LocalActivityManager是Android封裝的把activity轉換成view對象的一個api.

2.LocalActivityManager用法

LocalActivityManager類是管理activity的,然後通過startActivity(String id,Intent intent)這個方法獲取Window獲取當前Window對象,

再然後調用getDecorView()方法獲取當前activity對應的view,然而在添加view對象的時候會遇到這個問 題:

Caused by: java.lang.IllegalStateException: Activities can't be added until the containing group has been created.
解決辦法:

    LocalActivityManager mLocalActivityManager;

    oncreate()方法實例化mLocalActivityManager = new LocalActivityManager((Activity) context, true);

    在oncreate,onresume,onpause方法中分別加入如下代碼:

    oncreate()--------------mLocalActivityManager.dispatchCreate(arg0);參數arg0為oncreate方法的形參

    onpause()--------------mLocalActivityManager.dispatchPause(isFinishing());傳入true

    onresume()--------------mLocalActivityManager.dispatchResume();

LocalActivityManager的內部機制詳解

LocalActivityManager的內部機制

LocalActivityManager內部機制的核心在於,它使用了主線程對象mActivityThread來裝載指定的Activity。注意,這裡是裝載,而不是啟動,這點很重要。

所謂的啟動,一般是指會創建一個進程(如果所在應用進程還不存在)運行該Activity,而裝載僅僅是指把該Activity作為一個普通類進行加載,並創建一個該類的對象而已,而該類的任何函數都沒有被運行。

LocalActivityManager提供了一個重要方法startActivity(),該方法正是利用主線程mActivityThread去裝載指定的Activity,其執行過程如圖10-25所示。

LocalActivityManager類中startActivity()的執行流程

Manager對象必須已經被初始化,初始化的工作是在dispatchCreate()方法中首先被完成的,而這又是在 ActivityGroup類中的onCreate()中被調用的。也就是說,LocalActivityManager的 startActivity()方法必須在所在的Activity的onCreate()方法執行完畢後被調用。

判斷目標Activity是否包含在該Manager中。Manager中使用兩個列表變量保存已經裝載過的Activity對象,分別是 mActivities和mActivityArray。前者是一個HashMap類型,每一個LocalActivityRecord按照一個字符串對 應;後者是一個ArrayList列表。

判斷裝載的Activity對象是否有正處於resume狀態的,如果有,則要先暫停,事實上可以完全不用暫停,暫停僅僅是Manager希望完全 按照Activity對象本身的執行順序調用它,從而使得看上去更像是一個標准的子Activity啟動方式。而暫停則是通過調用 moveToState()完成的。

如果目標Activity已經被裝載到了當前Manager中,下面就需要判斷是直接使用該Activity的當前窗口呢,還是需要先銷毀該 Activity,並重新調用其onCreate()?注意,這裡所說的銷毀僅僅是指把Activity變成”銷毀”的狀態而已,並不是說銷毀該 Activity對象。而判斷的規則有點類似於AmS中根據Activity的flag執行不同的操作,其中包括是否先調用目標Activity的 onNewIntent(),還包括是否是CLEAR_TOP模式。一般作為TabActivity的嵌入式Activity都不會是CLEAR_TOP 模式,否則,如果多個Tab頁使用同一個Activity對象將導致所顯示的內容完全相同。

調用moveToState()改變指定Activity到resume狀態。

返回Activity所對應的Window窗口。

從以上步驟可以看出,裝載Activity對象的過程對AmS來講是完全不可見的,因為這是裝載而不是啟動,因此看似TabActvity同時運行 了多個Activity,而實際上僅僅是運行了ActivityGroup一個Activity。那些嵌入的Activity僅僅是貢獻了自己所包含的 Window窗口而已,TabActivity正是把這些Window窗口的DecorView作為tabcontent的子視圖而已。

下面對moveToState(LocalActivityRecord r, int desireState)函數的過程進行說明,參數r代表目標Activity對象,desireState代表期望把目標Activity改變成哪種狀態。

moveToState()函數內部首先判斷r.curState是否是RESTORED或者DESTROY狀態,如果是則直接返回。因為 RESTORED代表剛剛創建了目標Activity對象,還沒有執行onCreate()方法,所以不能改變狀態;DESTROY代表已經銷毀,也不能 改變狀態。

接著,判斷r.curState是否是INITIALIZE狀態,這種情況只有在第一次調用startActivity()裝載目標 Activity對象時才會執行到,其內部主要包括調用startActivityNow()和performResumeActivity()將目標 Activity改變到STARTED或者RESUMED狀態。

由於Activity當前狀態不同,要想達到不同的期望狀態自然需要經過不同的步驟。moveToState()函數內部正是使用switch語句 先判斷當前處於什麼狀態,然後再在case裡面使用if…else語句判斷期望的狀態,最後再調用不同的函數。其狀態和調用關系如表10-8所示,該表中 調用的函數名稱使用了簡寫,比如performRestartActivity簡寫為Restart。

表10-8 Activity在不同狀態中轉換時需執行的操作

目標狀態

當前狀態

CREATED

STARTED

RESUMED

CREATED

Restart ();

Restart();

Resume();

STARTED

Stop();

Resume();

RESUMED

Pause();

Stop();

Pause();

從以上的步驟可以看出,startActivity()的內部執行邏輯有點像AmS中根據當前Activity狀態調用不同方法。這兩者就像《西游 記》中的小雷音寺和大雷音寺,兩者的本質區別在於LocalActivityManager僅僅是為了獲取Activity對應的Window對象,中間 的狀態切換僅僅是為了保證Activity本身的執行過程,從而保證Window對象的視圖內容有一個正確的呈現。

ActivityGroup內部的Activity生命期控制

前面分析了LocalActivityManager內部的執行原理,接下來分析一個有意思的問題:”在TabActivity的多個Tab頁切換時,內嵌的Activity對象會在onPause()和onResume()之間切換嗎?”

從上面的分析可知,Manager裝載Activity的目的僅僅是為了獲取其所包含的Window對象,而一旦獲取後,則似乎不需要再糾纏於 Activity本身的生命期狀態變換操作。其實筆者也是這麼認為的,可以嘗試屏蔽以下代碼,該段代碼的作用是在裝載下一個Activity之前先暫停當 前的Activity對象。

屏蔽後,運行結果絲毫不受影響,原因很簡單,這裡做暫停的目的僅僅為了保持Activity原有的生命期過程,從而可以保持原有Activity釋 放相關資源的行為。比如當Activity A以啟動的方式運行時,如果另一個Activity B要啟動,則會先暫停A。在一般的程序設計中,暫停會回調onPause()操作,如果該Activity使用了大量的內存或者其他資源,在 onPause()函數中程序員可能會嘗試釋放這些資源以提高系統效率,這就是為什麼在LocalActivityManager中也保持了這種流程的原 因。當然,如果你不釋放,也不會發生什麼邏輯錯誤。

而在以上代碼的moveToState()操作中調用了mActivityThread的onPause()或者onStop()操作,這就是為什 麼在Tab頁切換時,對應的Activity也會執行onPause()或者onStop()的原因。這完全與AmS無關,因此不要因為這個而產生 TabActivity同時運行了兩個Activity(TabActivity本身和嵌入的Activity)的錯覺。

另外還有一個有意思的問題,請思考下面的操作過程。

打開一個TabActivity,比如”聯系人”程序,在上面的四個Tab頁上都點一次,然後再按”Home”鍵回到桌面,然後再從聯系人圖標中進入該程序。請思考此時TabActivity內嵌的Activity會發生生命期狀態改變嗎?

首先TabActivity當然會從stop狀態轉變為start狀態,並先後調用onStart()和onPause()。因為它是一個標准的 Activity,TabActivity的父類是ActivityGroup,而在該類中,相應的onXXX()方法內部都增加了 mLocalActivityManager.dispatchXXX()代碼,比如:

 protected void onResume() {
    mLocalActivityManager.dispatchResume();
 };

而在LocalActivityManager中,dispatchXXX()則會把相應的 action再dispatch到所包含的所有嵌入式Activity對象中。所以,以上問題的答案是內嵌的Activity生命期會從stop狀態轉換 到resume狀態。仔細查看ActivityGroup的onXXX()函數發現,唯獨沒有onStart()方法,其原因是在 LocalActivityManager的moveToState()方法中可以直接把子Activity的狀態從stop改變到resume,所以, 此處可以省略對onStart()的重載。
1.LocalActivityManager的說明

LocalActivityManager是Android封裝的把activity轉換成view對象的一個api.

2.LocalActivityManager用法

LocalActivityManager類是管理activity的,然後通過startActivity(String id,Intent intent)這個方法獲取Window獲取當前Window對象,

再然後調用getDecorView()方法獲取當前activity對應的view,然而在添加view對象的時候會遇到這個問 題:

Caused by: java.lang.IllegalStateException: Activities can't be added until the containing group has been created.
解決辦法:

    LocalActivityManager mLocalActivityManager;

    oncreate()方法實例化mLocalActivityManager = new LocalActivityManager((Activity) context, true);

    在oncreate,onresume,onpause方法中分別加入如下代碼:

    oncreate()--------------mLocalActivityManager.dispatchCreate(arg0);參數arg0為oncreate方法的形參

    onpause()--------------mLocalActivityManager.dispatchPause(isFinishing());傳入true

    onresume()--------------mLocalActivityManager.dispatchResume();

LocalActivityManager的內部機制詳解

LocalActivityManager的內部機制

LocalActivityManager內部機制的核心在於,它使用了主線程對象mActivityThread來裝載指定的Activity。注意,這裡是裝載,而不是啟動,這點很重要。

所謂的啟動,一般是指會創建一個進程(如果所在應用進程還不存在)運行該Activity,而裝載僅僅是指把該Activity作為一個普通類進行加載,並創建一個該類的對象而已,而該類的任何函數都沒有被運行。

LocalActivityManager提供了一個重要方法startActivity(),該方法正是利用主線程mActivityThread去裝載指定的Activity,其執行過程如圖10-25所示。

LocalActivityManager類中startActivity()的執行流程

Manager對象必須已經被初始化,初始化的工作是在dispatchCreate()方法中首先被完成的,而這又是在 ActivityGroup類中的onCreate()中被調用的。也就是說,LocalActivityManager的 startActivity()方法必須在所在的Activity的onCreate()方法執行完畢後被調用。

判斷目標Activity是否包含在該Manager中。Manager中使用兩個列表變量保存已經裝載過的Activity對象,分別是 mActivities和mActivityArray。前者是一個HashMap類型,每一個LocalActivityRecord按照一個字符串對 應;後者是一個ArrayList列表。

判斷裝載的Activity對象是否有正處於resume狀態的,如果有,則要先暫停,事實上可以完全不用暫停,暫停僅僅是Manager希望完全 按照Activity對象本身的執行順序調用它,從而使得看上去更像是一個標准的子Activity啟動方式。而暫停則是通過調用 moveToState()完成的。

如果目標Activity已經被裝載到了當前Manager中,下面就需要判斷是直接使用該Activity的當前窗口呢,還是需要先銷毀該 Activity,並重新調用其onCreate()?注意,這裡所說的銷毀僅僅是指把Activity變成”銷毀”的狀態而已,並不是說銷毀該 Activity對象。而判斷的規則有點類似於AmS中根據Activity的flag執行不同的操作,其中包括是否先調用目標Activity的 onNewIntent(),還包括是否是CLEAR_TOP模式。一般作為TabActivity的嵌入式Activity都不會是CLEAR_TOP 模式,否則,如果多個Tab頁使用同一個Activity對象將導致所顯示的內容完全相同。

調用moveToState()改變指定Activity到resume狀態。

返回Activity所對應的Window窗口。

從以上步驟可以看出,裝載Activity對象的過程對AmS來講是完全不可見的,因為這是裝載而不是啟動,因此看似TabActvity同時運行 了多個Activity,而實際上僅僅是運行了ActivityGroup一個Activity。那些嵌入的Activity僅僅是貢獻了自己所包含的 Window窗口而已,TabActivity正是把這些Window窗口的DecorView作為tabcontent的子視圖而已。

下面對moveToState(LocalActivityRecord r, int desireState)函數的過程進行說明,參數r代表目標Activity對象,desireState代表期望把目標Activity改變成哪種狀態。

moveToState()函數內部首先判斷r.curState是否是RESTORED或者DESTROY狀態,如果是則直接返回。因為 RESTORED代表剛剛創建了目標Activity對象,還沒有執行onCreate()方法,所以不能改變狀態;DESTROY代表已經銷毀,也不能 改變狀態。

接著,判斷r.curState是否是INITIALIZE狀態,這種情況只有在第一次調用startActivity()裝載目標 Activity對象時才會執行到,其內部主要包括調用startActivityNow()和performResumeActivity()將目標 Activity改變到STARTED或者RESUMED狀態。

由於Activity當前狀態不同,要想達到不同的期望狀態自然需要經過不同的步驟。moveToState()函數內部正是使用switch語句 先判斷當前處於什麼狀態,然後再在case裡面使用if…else語句判斷期望的狀態,最後再調用不同的函數。其狀態和調用關系如表10-8所示,該表中 調用的函數名稱使用了簡寫,比如performRestartActivity簡寫為Restart。

表10-8 Activity在不同狀態中轉換時需執行的操作

目標狀態

當前狀態

CREATED

STARTED

RESUMED

CREATED

Restart ();

Restart();

Resume();

STARTED

Stop();

Resume();

RESUMED

Pause();

Stop();

Pause();

從以上的步驟可以看出,startActivity()的內部執行邏輯有點像AmS中根據當前Activity狀態調用不同方法。這兩者就像《西游 記》中的小雷音寺和大雷音寺,兩者的本質區別在於LocalActivityManager僅僅是為了獲取Activity對應的Window對象,中間 的狀態切換僅僅是為了保證Activity本身的執行過程,從而保證Window對象的視圖內容有一個正確的呈現。

ActivityGroup內部的Activity生命期控制

前面分析了LocalActivityManager內部的執行原理,接下來分析一個有意思的問題:”在TabActivity的多個Tab頁切換時,內嵌的Activity對象會在onPause()和onResume()之間切換嗎?”

從上面的分析可知,Manager裝載Activity的目的僅僅是為了獲取其所包含的Window對象,而一旦獲取後,則似乎不需要再糾纏於 Activity本身的生命期狀態變換操作。其實筆者也是這麼認為的,可以嘗試屏蔽以下代碼,該段代碼的作用是在裝載下一個Activity之前先暫停當 前的Activity對象。

屏蔽後,運行結果絲毫不受影響,原因很簡單,這裡做暫停的目的僅僅為了保持Activity原有的生命期過程,從而可以保持原有Activity釋 放相關資源的行為。比如當Activity A以啟動的方式運行時,如果另一個Activity B要啟動,則會先暫停A。在一般的程序設計中,暫停會回調onPause()操作,如果該Activity使用了大量的內存或者其他資源,在 onPause()函數中程序員可能會嘗試釋放這些資源以提高系統效率,這就是為什麼在LocalActivityManager中也保持了這種流程的原 因。當然,如果你不釋放,也不會發生什麼邏輯錯誤。

而在以上代碼的moveToState()操作中調用了mActivityThread的onPause()或者onStop()操作,這就是為什 麼在Tab頁切換時,對應的Activity也會執行onPause()或者onStop()的原因。這完全與AmS無關,因此不要因為這個而產生 TabActivity同時運行了兩個Activity(TabActivity本身和嵌入的Activity)的錯覺。

另外還有一個有意思的問題,請思考下面的操作過程。

打開一個TabActivity,比如”聯系人”程序,在上面的四個Tab頁上都點一次,然後再按”Home”鍵回到桌面,然後再從聯系人圖標中進入該程序。請思考此時TabActivity內嵌的Activity會發生生命期狀態改變嗎?

首先TabActivity當然會從stop狀態轉變為start狀態,並先後調用onStart()和onPause()。因為它是一個標准的 Activity,TabActivity的父類是ActivityGroup,而在該類中,相應的onXXX()方法內部都增加了 mLocalActivityManager.dispatchXXX()代碼,比如:

 protected void onResume() {
    mLocalActivityManager.dispatchResume();
 };

而在LocalActivityManager中,dispatchXXX()則會把相應的 action再dispatch到所包含的所有嵌入式Activity對象中。所以,以上問題的答案是內嵌的Activity生命期會從stop狀態轉換 到resume狀態。仔細查看ActivityGroup的onXXX()函數發現,唯獨沒有onStart()方法,其原因是在 LocalActivityManager的moveToState()方法中可以直接把子Activity的狀態從stop改變到resume,所以, 此處可以省略對onStart()的重載。

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