發現當前Android的資料不是很多,而且對于Activity的介紹也很少,所以把官方文檔的android.app.Activity的介紹翻譯了一下,加入了一些自己的理解。各位如果覺得我自己理解的不對,請無視。歡迎郵件討論。
android.app
public class
android.app.Activity
android.app.ApplicationContext ?? ViewInflate.Factory
android.app.Activity ???? KeyEvent.Callback Window.Callback
?
?
Activity 是用戶唯一可以看得到的東西。幾乎所有的 activity 都與用戶進行交互,所以 Activity 主要負責的就是創建顯示窗口,你可以在這些窗口里使用 setContentView(View) 來顯示你自己的 UI 。 activity 展現在用戶面前的經常是全屏窗口,你也可以將 activity 作為浮動窗口來使用(使用設置了 windowIsFloating 的主題),或者嵌入到其他的 activity (使用 ActivityGroup )中。下面是兩個幾乎所有 Activity 的子類都實現了的方法。
onCreate(Bundle) 這個方法是初始化 activity 的地方 . 最重要的是,你經常需要在這里使用 setContentView(int) 來設置 UI 布局所使用的 layout 資源 , 當你需要使用程序控制 UI 中的組件時可以使用 findViewById(int) 來獲得對應的視圖。
當用戶離開 activity 時你可以在 onPause() 進行相應的操作 . 更重要的是,用戶做的任何改變都應該在該點上提交 ( 經常提交到 ContentProvider 這里保存數據 ) 。
如果要使用
Context.startActivity()
來啟動
activity, activity
都必須在啟動者應用包的
AndroidManifest.xml
文件中
有對應的
<activity>
定義。
?
Activity 類是 application's overall lifecycle 的一個重要部分。
?
這里涉及到的主題 :
Activity 生命周期
系統中的 Activity 可以通過一個 activity 棧來進行管理。當一個新的 activity 啟動的時候,它首先會被放置在 activity 棧頂部并成為 running 狀態的 activity —— 之前的 activity 也在 activity 棧中,但總是被保存在它的下邊,只有當這個新的 activity 退出以后之前的 activity 才能重新回到前景界面。
?
所有的 activity 本質上有四種狀態:
- activity 在屏幕的前景中( activity 棧的頂端),它是 active 或者 running 狀態。
?
- activity 失去了焦點但是仍然可見(這個 activity 頂上遮擋了一個透明的或者非全屏的 activity ),它的狀態是 paused 。一個 paused 狀態的 activity 完全是 alive 的(它維護自己所有的狀態和成員信息,而且仍然在 window manager 的管理中),但當系統內存極度貧乏時也會將其 killed 。
?
- activity 由于其他的 activity 而完全變暗,它就進入了 stopped 狀態。它仍然保持著所有的狀態和成員的信息,可是,他對于用戶來說不可見,當別的地方需要內存的時候它經常會被 killed 。
- activity 是 paused 或者 stopped ,系統需要將其清理出內存的時可以命令其 finish 或者簡單 kill 其進程。當它重新在用戶面前顯示的時候,它必須完全重新啟動并且將其關閉之前的狀態全部恢復回來。
下面的圖表是 Activity 的狀態圖,直角矩形代表了 callback 方法,你可以實現這些方法從而使 Activity 在改變狀態的時候執行你制定的操作。帶顏色的橢圓形是 Activity 的主要狀態。
?
?
? 這里有三個比較關鍵的生命周期。
- 從最初 調用 onCreate(Bundle) 到最終調用 onDestroy() 稱為 完整生命周期 。 Activity 會在 onCreate() 進行所有“全局”狀態的設置,在 onDestroy() 中釋放所有持有的資源。舉個例子,如果它有一個從網絡上下載數據的后臺線程,那他可能就會在 onCreate() 中創建這個線程并在 onDestroy() 中停止這個線程。
- 從 activity 調用 onStart() 開始,到調用對應的 onStop() 為止稱為 可見生命周期 。在這段時間內用戶可以在屏幕上看到這個 activity ,盡管并不一定是在前景也不一定可以和用戶交互。在這兩個方法之間你可以維護那些 activity 在用戶顯示時所需的資源。舉個例子來說,你可以在 onStart() 中注冊一個 IntentReceiver 來監控那些可以對你的 UI 產生影響的環境改變,當你的 UI 不繼續在用戶面前顯示時你可以在 onStop() 中注銷這個 IntentReceiver 。每當 activity 在用戶面前顯示或者隱藏時都會調用相應的方法,所以 onStart() 和 onStop() 方法在整個生命周期中可以多次被調用。
- 從 activity 調用 onResume() 開始,到調用對應的 onPause() 為止稱為 前景生命周期 ,這段時間 activity 處于其他所有 activity 的前面,且與用戶交互。一個 activity 可以經常在 resumed 和 paused 狀態之間轉換——例如手機進入休眠時、 activity 的結果返回時、新的 intent 到來時——所以這兩個方法中的代碼應該非常的簡短。
下面的 Activity 方法定義了 activity 完整的生命周期。他們全都是 hook 方法,你可以重載這些方法從而使 activity 在狀態改變時執行你所期望的操作。所有 activity 都應該實現自己的 onCreate(Bundle) 方法來進行初始化設置;大部分還應該實現 onPause() 方法提交數據的修改并且準備終止與用戶的交互。盡管我們計劃在系統中添加更多的工具來管理應用,現在大多 activity 仍需要實現 onFreeze() 并且在 onCreate(Bundle) 中執行對應的狀態恢復。其他的方法可以在需要時進行實現,當實現這些方法的時候需要注意的是一定要調用父類中的對應方法。
?
public class Activity extends ApplicationContext {
protected void onCreate(Bundle icicle);
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onFreeze(Bundle outIcicle);
protected void onPause();
protected void onStop();
protected void onDestroy();
}
?
?
?
一般來說 activity 的生命周期變化看起來比較象下面的表格:?
(此處譯者進行了大塊的修改,請參考 原文 閱讀下面表格)
?
方法 |
描述 |
Killable? |
下一方法 |
|
Activity 初次創建時被調用,你應該在這里進行一般的靜態設置:創建 view 、將數據綁定到 list 等等。如果 activity 之前存在凍結狀態,那么此狀態將在 Bundle 中提供。 如果 activity 首次創建,本方法后將會調用 onStart() ,如果 activity 是停止后重新顯示,則將調用 onRestart() 。 |
No |
|
||
? |
當 activity 對用戶即將可見的時候調用。 其后調用 onRestart() 或 onResume() ( 框架是否進行選擇性調用 onResume() 僅僅是猜測 ) |
No |
|
|
當 activity 從停止狀態重新啟動時調用。其后調用 onResume() 。 |
No |
|
||
? |
當 activity 將要與用戶交互時調用此方法,此時 activity 在 activity 棧的棧頂,用戶輸入已經可以傳遞給它。 如果其他的 activity 在它的上方恢復顯示,則將調用 onFreeze() 。 |
No |
|
|
當你的 activity 被暫停而其他的 activity 恢復與用戶交互的時候這個方法會被調用(在其他 activity 顯示之前),你可以使用這個方法保存你當前的用戶狀態(一般來說是當前實例的用戶狀態)。暫停之后,為了回收資源供給前景 activity ,系統會在需要的時間停止(或者 kill )你的應用。以后如果你的 activity 啟動一個新的實例重新與用戶進行交互,你保存在這里的狀態都將通過 onCreate() 方法傳遞給新的實例。 其后總是調用 onPause() 方法。 |
No |
|
||
當系統要啟動一個其他的 activity 時調用(其他的 activity 顯示之前),這個方法被用來提交那些持久數據的改變、停止動畫、和其他占用 CPU 資源的東西。由于下一個 activity 在這個方法返回之前不會 resumed ,所以實現這個方法時代碼執行要盡可能快。 如果 activity 重新回到前景時將調用 onResume() , 如果對用戶徹底不可見則會調用 onStop() 。 |
Yes |
|
||
當另外一個 activity 恢復并遮蓋住此 activity, 導致其對用戶不再可見時調用。一個新 activity 啟動、其它 activity 被切換至前景、當前 activity 被銷毀時都會發生這種場景。 當 activity 重新回到前景與用戶交互時調用 onRestart() ,如果 activity 將退出則調用 onDestory() 。 |
Yes |
|
||
在你的 activity 被銷毀前所調用的最后一個方法,當進程終止時會出現這種情況(對 activity 直接調用 finish() 方法或者系統為了節省空間而臨時銷毀此 activity 的實例,你可以通過 isFinishing() 的返回值來區分這兩種情況)。 |
Yes |
nothing |
① : 這個表格本人覺得還有些值得商榷的地方,建議作為參考閱讀,不管是原文還是譯文。
?
注意上表中“ Killable ”這一列 —— 對于那些標記 killable 的方法,當這些方法結束后, activity 的進程可能在任何時間被系統 kill 而不再執行 activity 中的任何代碼。因此你應該利用 onFreeze() (保存你當前 UI 的狀態)和 onPause() (將所有的修改寫回持久存儲),這樣 activity 才能在被 kill 的時候正確的保存當前的狀態。如果需要了解一個進程的生命周期與他所執行的 activity 之間的關系 參見 進程生命周期 部分。
?
?????? 對于那些標記 killable 的方法,從這些方法啟動開始直到返回之前, activity 的進程都不回被系統 kill 。舉個例子,一個 activity 在 onPause() 方法返回后處于 killable 的狀態,這種狀態會一直持續到 onResume() 方法開始執行。
?
配置改變
如果設備的配置(在 Resources.Configuration 中進行了定義)發生改變,那么所有用戶界面上的東西都需要進行更新,以適應新的配置。因為 Activity 是與用戶交互的最主要的機制,它包含了處理配置改變的專門支持。
?
?????? 除非你特殊指定,否則當配置發生改變(比如屏幕方向、語言、輸入設備等等的改變)時你當前的 activity 都將被銷毀,這銷毀是通過一個正常的 activity 生命周期過程( onFreeze(Bundle) , onPause() , onStop() , 和 onDestroy() )進行的。如果 activity 之前正在前景畫面,當這個實例的 onDestroy() 調用完成后將會啟動這個 activity 的一個新的實例,并將前面那個實例中 onFreeze(Bundle) 所保存的內容傳遞給新的實例。
?
因為任何的應用資源(包括 layout 文件)都有可能由于任何配置值而改變。因此處理配置改變的唯一安全的方法就是重新獲取所有的資源,包括 layout 、繪圖資源(原文 drawables )、字符串資源。由于 activity 已經如何保存自己的狀態并從這些狀態中重建自身,所以 activity 重新啟動自身來獲得新的配置將是一個非常便利的途徑。
?
?????? 在一些特殊的情況中,你可能希望當一種或者多種配置改變時避免重新啟動你的 activity 。你可以通過在 manifest 中設置 android:configChanges 屬性來實現這點。你可以在這里聲明 activity 可以處理的任何配置改變,當這些配置改變時不會重新啟動 activity ,而會調用 activity 的 onConfigurationChanged(Resources.Configuration) 方法。如果改變的配置中包含了你所無法處理的配置(在 android:configChanges 并未聲明),你的 activity 仍然要被重新啟動,而 onConfigurationChanged(Resources.Configuration) 將不會被調用。
?
啟動 Activity 并獲得結果
startActivity(Intent) 方法可以用來啟動一個新的 activity ,這個 activity 將被放置在 activity 棧的棧頂。這個方法只有一個參數 Intent ,這個參數描述了將被執行的 activity 。
?
?????? 有時候你希望在一個 activity 結束時得到它返回的結果。舉個例子,你可能啟動一個 activity 來讓用戶從通訊簿中選擇一個人;當它結束的時候將會返回這個所選擇的人。為了得到這個返回的信息,你可以使用 startSubActivity(Intent, int) 這個方法來啟動新的 activity ,第二個整形參數將會作為這次調用的識別標記。這個 activity 返回的結果你可以通過 onActivityResult(int, int, String, Bundle) 方法來獲得,此方法的第一個參數就是之前調用所使用的識別標記。
?
??????
當
activity
退出的時候,它可以調用
setResult(int)
來將數據返回給他的父進程。這個方法必須提供一個結果碼,這個結果碼可以使標準結果
RESULT_CANCELED, RESULT_OK
,也可以是其他任何從
RESULT_FIRST_USER
開始的自定義值。此外,它還可以返回一段字符串(經常是一段數據的
URL
地址),一個包含它所有希望值的
Bundle
。這些信息都會在父
activity
的回調函數
Activity.onActivityResult()
中出現,并連同最初提供的識別標記一起(此處有些拗口,意思其實就是子
activity
返回的內容、返回碼、識別標記都將作為參數,按照不同的返回情況來調用父
activity
的
Activity.onActivityResult()
方法,以實現出現各種返回時父
activity
做出響應的處理)。
?
?????? 如果子 activity 由于某種情況發生失敗(例如 crashing ),父 activity 將會收到 RESULT_CANCELED 結果碼。
?
?????? 這里是一個例子,說明了如何啟動一個新的 activity 并處理結果。
?
public class CalendarActivity extends Activity {
...
static final int DAY_VIEW_MODE = 0;
static final int WEEK_VIEW_MODE = 1;
private SharedPreferences mPrefs;
private int mCurViewMode;
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
SharedPreferences mPrefs = getSharedPreferences();
mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE);
}
protected void onPause() {
super.onPause();
SharedPreferences.Editor ed = mPrefs.edit();
ed.putInt("view_mode", mCurViewMode);
ed.commit();
}
}
?
許可你可以通過在 Activity 所屬應用的 manifest 文件中對應的 <activity> 標簽中進行
聲明來限制哪些應用可以啟動此 Activity 。如果你進行了聲明,其它應用需要在他們
自己的 manifest 文件中聲明對應的 <uses-permission> 元素( 而且需要在安裝時
被授予許可:譯者注 )才可以啟動這個 activity 。
?
如果需要了解更多有關于一般安全機制和許可方面的信息可以參考 Security Model 。
進程生命周期
Android 系統會盡量久的保留應用進程。但是當內存降低時最終還是要移除舊的進程。就像 Activity 生命周期 中描述的一樣,移除哪個進程還是要取決于關聯的用戶與之交互的程度。一般來說,進程可以基于其中運行的 activity 所處的生命周期而分成四種狀態,下面將這些狀態根據重要程度排列。系統會在 kill 更重要的進程(第一個)之前首先 kill 那些不那么重要的進程(最后一個)。
?
前景 activity (處于屏幕最上方,用戶與之交互的 activity )被認為是最重要的。如果設備上的內存無法滿足它的使用, Kill 此進程只能作為最后的手段。一般來說這個時候設備處于內存 paging 狀態,為了
使用戶界面保持響應才會發出這個 kill 請求。
可見 activity (一個對用戶可見,但是不在前景的 activity ,比如處在浮動對話框后)被認為是非常重要的,除非為了保證前景 activity 運行,否則不會被 kill 。
后臺 activity (一個對用戶不可見,并處于 paused 狀態的 activity )就不再重要了,所以當需要為其它前景的或者可見的 activity 運行而回收內存時系統可以很安全的 kill 它們。
空進程 是一個沒有運行 activity 或者其他應用組件(比如 Service 或者 IntentReceiver 類)的進程。當內存開始降低時系統很快就會 kill 掉這些進程。因此當你要在 activity 外運行任何的后臺操作時,必須在 IntentReceiver 或 Service 的上下文環境中運行,這樣系統才知道需要將你的進程保留而不是 kill 。
有些時候 Activity 可能需要長時間運行一個操作,且它并不依賴于 activity 的生命周期而存在。例如一個照相機應用可能允許你將照片上傳到 web 站點。上傳可能需要很長時間,在上傳過程中應該允許用戶離開這個應用。為了做到這一點,你的 activity 應該在上傳時啟動一個 Service 來執行此工作。這將使系統在你的進程上傳數據的過程中能夠恰當的區分它的優先級(認為此進程比其他不可見應用更重要),不管原來的 activity 的狀態是 paused 、 stopped 還是 finished 。
?
marshal.hird@gmail.com
?
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
