線程安全方法(Thread-safe methods)
在一些情況下,你所實作的方法有可能會被多于一個的線程所調用,是以它們必須被寫成線程安全的。
對于我們上一節所讨論的RPC機制中的可以被遠端調用的方法來說,這是必須首先考慮的。如果針對一個IBinder對象中實作的方法的調用源自這個 IBinder對象所在的程序時,這個方法将會在調用者的線程中執行。然而,如果這個調用源自其它的程序,則這個方法将會在一個線程池中選出的線程中運 行,這個線程池由Android加以管理,并與IBinder存在于同一程序内;這個方法不會在程序的主線程内執行。反過來說,一個服務的 onBind() 方法應為服務程序的主線程所調用,而實作了由 onBind() 傳回的對象(比如說,一個實作了RPC方法的Stub的子類)的方法将為池中的線程所調用。因為服務可以擁有多于一個的用戶端,而同一時間,也會有多個池中的線程調用同一個IBinder方法。是以IBinder方法必須實作為線程安全的。
應用程式元件有其生命周期──由Android初始化它們以相應intent直到這個執行個體被摧毀。在此之間,它們有時是激活的有時則相反。或者,如果它是 一個activity,則是可為使用者所見或者不能。這一節讨論了activity、服務以及廣播接收器的生命周期,包括它們在生命周期中的狀态、在狀态之 間轉變時通知你的方法、以及當這些程序被關閉或執行個體被摧毀時,這些狀态産生的效果。
Activity生命周期(Activity lifecycle)
一個activity主要有三個狀态:
* 當在螢幕前台時(位于目前任務堆棧的頂部),它是活躍或運作的狀态。它就是相應使用者操作的activity。
* 當它失去焦點但仍然對使用者可見時,它處于暫停狀态。即是:在它之上有另外一個activity。這個activity也許是透明的,或者未能完全遮蔽全屏,是以被暫停的activity仍對使用者可見。暫停的activity仍然是存活狀态(它保留着所有的狀态和成員資訊并連接配接至視窗管理器),但當系統處于極低記憶體的情況下,仍然可以殺死這個activity。
* 如果它完全被另一個activity覆寫是,它處于停止狀态。它仍然保留所有的狀态和成員資訊。然而它不在為使用者可見,是以它的視窗将被隐藏,如果其它地方需要記憶體,則系統經常會殺死這個activity。
當一個activity從這個狀态轉變到另一個狀态時,它被以下列protected方法所通知:
void onCreate(Bundle savedInstanceState)
void onStart()
void onRestart()
void onResume()
void onPause()
void onStop()
void onDestroy()
調用父類(Calling into the superclass)
所有activity生命周期方法的實作都必須先調用其父類的版本。比如說:
總得來說,這七個方法定義了一個activity完整的生命周期。實作這些方法可以幫助你監察三個嵌套的生命周期循環:
* 一個activity 完整的生命周期 自第一次調用 onCreate()開始,直至調用onDestroy()為止。activity在onCreate()中設定所有“全局”狀态以完成初始化,而在onDestroy()中釋放所有系統資源。比如說,如果activity有一個線程在背景運作以從網絡上下載下傳資料,它會以 onCreate()<code>建立那個線程,而以</code> onDestroy()銷毀那個線程。
* 一個activity的 可視生命周期自 onStart() 調用開始直到相應的 onStop()調用。在此期間,使用者可以在螢幕上看到此activity,盡管它也許并不是位于前台或者正在與使用者做互動。在這兩個方法中,你可以管控用來向使用者顯示這個activity的資源。比如說,你可以在onStart() 中注冊一個BroadcastReceiver 來監控會影響到你UI的改變,而在onStop() 中來取消注冊,這時使用者是無法看到你的程式顯示的内容的。onStart() 和 onStop() 方法可以随着應用程式是否為使用者可見而被多次調用。
* 一個activity的 前台生命周期 自 onResume() 調用起,至相應的 onPause()調用為止。在此期間,activity位于前台最上面并與使用者進行互動。activity會經常在暫停和恢複之間進行狀态轉換──比如說當裝置轉入休眠狀态或有新的activity啟動時,将調用onPause() 方法。當activity獲得結果或者接收到新的intent的時候會調用onResume() 方法。是以,在這兩個方法中的代碼應當是輕量級的。
下圖展示了上述循環過程以及activity在這個過程之中曆經的狀态改變。着色的橢圓是activity可以經曆的主要狀态。矩形框代表了當activity在狀态間發生改變的時候,你進行操作所要實作的回調方法。
下表較長的描述了這些方法,并在activity的整個生命周期中定位了它們。
方法
描述
是否可被殺死(Killable?)
下一個
接下來始終遵循調用onStart()。
否
onStart()
在activity停止後,在再次啟動之前被調用。
當activity正要變得為使用者所見時被調用。
當activity轉向前台時接下來調用onResume(),在activity變為隐藏時接下來調用onStop()。
onResume()
或
onStop()
在activity開始與使用者進行互動之前被調用。此時activity位于堆棧頂部,并接受使用者輸入。
接下來始終遵循調用onPause()。
<code>onPause()</code>
當系統将要啟動另一個activity時調用。此方法主要用來将未儲存的變化進行持久化,停止類似動畫這樣耗費CPU的動作等。這一切動作應該在短時間内完成,因為下一個activity必須等到此方法傳回後才會繼續。
當activity重新回到前台時接下來調用onResume()。當activity變為使用者不可見時接下來調用onStop()。
是
當activity不再為使用者可見時調用此方法。這可能發生在它被銷毀或者另一個activity(可能是現存的或者是新的)回到運作狀态并覆寫了它。
如果activity再次回到前台跟使用者互動則接下來調用onRestart(),如果關閉activity則接下來調用onDestroy()。
onRestart()
or
onDestroy()
無
請注意上表中可被殺死一列。它标示了在方法傳回後,還沒執行activity的其餘代碼的任意時間裡,系統是否可以殺死包含此activity的程序。三個方法(onPause()、 onStop()<code>和</code>onDestroy())被标記為“是”。onPause()是三個中的第一個,它也是唯一一個在程序被殺死之前必然會調用的方法──onStop() 和 onDestroy() 有可能不被執行。是以你應該用 onPause() 來将所有持久性資料(比如使用者的編輯結果)寫入存儲之中。
在可被殺死一列中标記為“否”的方法在它們被調用時将保護activity所在的程序不會被殺死。是以隻有在onPause()<code>方法傳回後到</code>onResume() 方法被調用時,一個activity才處于可被殺死的狀态。在onPause()<code>再次被調用并傳回之前,它不會被系統殺死。</code>
儲存activity狀态(Saving activity state)
當系統而不是使用者自己出于回收記憶體的考慮,關閉了一個activity之後。使用者會期望當他再次回到那個activity的時候,它仍保持着上次離開時的樣子。
與onPause()或先前讨論的其它方法不同,onSaveInstanceState() 和 onRestoreInstanceState() 并不是生命周期方法。它們并不是總會被調用。比如說,Android會在activity易于被系統銷毀之前調用 onSaveInstanceState(),但使用者動作(比如按下了BACK鍵)造成的銷毀則不調用。在這種情況下,使用者沒打算再次回到這個activity,是以沒有儲存狀态的必要。
因為onSaveInstanceState()不是總被調用,是以你應該隻用它來為activity儲存一些臨時的狀态,而不能用來儲存持久性資料。而是應該用onPause()來達到這個目的。
服務生命周期(Coordinating activities)
服務以兩種方式使用:
這兩種模式并不是完全分離的。你可以綁定至一個用 startService()啟動的服務。比如說,一個背景音樂播放服務可以調用startService()并傳遞給它一個包含欲播放的音樂清單的Intent對象來啟動。不久,當使用者想要對播放器進行控制或者檢視目前播放曲目的詳情時,會啟用一個activity,調用bindService()連接配接到服務來完成操作。在這種情況下,直到綁定連接配接關閉stopService() 才會真正停止一個服務。
與activity一樣,服務也有一系列你可以實作以用于監控其狀态變化的生命周期方法。但相對于activity要少一些,隻有三個,而且,它們是public屬性,并非protected:
void onCreate()
void onStart(Intent intent)
倚仗實作這些方法,你監控服務的兩個嵌套的生命周期循環:
服務停止時沒有相應的回調方法──不存在onStop()方法。
如果一個服務允許别的程序綁定,則它還會有以下額外的回調方法以供實作:
IBinder onBind(Intent intent)
boolean onUnbind(Intent intent)
void onRebind(Intent intent)
下圖描繪了服務的回調方法。盡管圖中對由startService 和startService方法啟動的服務做了區分,但要記住,不論一個服務是怎麼啟動的,它都可能允許用戶端的連接配接,是以任何服務都可以接受onBind()和onUnbind()調用。
廣播接收器生命周期(Broadcast receiver lifecycle)
廣播接收器隻有一個回調方法:
void onReceive(Context curContext, Intent broadcastMsg)
擁有一個活躍狀态的廣播接收器的程序被保護起來而不會被殺死。但僅擁有失活狀态元件的程序則會在其它程序需要它所占有的記憶體的時候随時被殺掉。
這種方式引出了一個問題:如果響應一個廣播資訊需要很長的一段時間,我們一般會将其納入一個衍生的線程中去完成,而不是在主線程内完成它,進而保證使用者互動過程的流暢。如果onReceive()衍生了一個線程并且傳回,則包涵新線程在内的整個程序都被會判為失活狀态(除非程序内的其它應用程式元件仍處于活躍狀态),于是它就有可能被殺掉。這個問題的解決方法是令onReceive()啟動一個新服務,并用其完成任務,于是系統就會知道程序中仍然在處理着工作。
下一節中,我們會讨論更多程序易誤殺的問題。
程序與生命周期(Processes and lifecycles)
Android系統會盡可能長的延續一個應用程式程序,但在記憶體過低的時候,仍然會不可避免需要移除舊的程序。為決定保留或移除一個程序,Android 将每個程序都放入一個“重要性層次”中,依據則是它其中運作着的元件及其狀态。重要性最低的程序首先被消滅,然後是較低的,依此類推。重要性共分五層,依 據重要性清單如下:
1. 前台程序是使用者操作所必須的。當滿足如下任一條件時,程序被認為是處于前台的:
* 一個正在與使用者互動的activity使用着它提供的一個服務。
任一時間下,僅有少數程序會處于前台,僅當記憶體實在無法供給它們維持同時運作時才會被殺死。一般來說,在這種情況下,裝置已然處于使用虛拟記憶體的狀态,必須要殺死一些前台程序以使用者界面保持響應。
2. 可視程序沒有前台元件,但仍可被使用者在螢幕上所見。當滿足如下任一條件時,程序被認為是可視的:
* 它包含了一個綁定至一個可視的activity的服務。
可視程序依然被視為是很重要的,非到不殺死它們便無法維持前台程序運作時,才會被殺死。
5. 空程序不包含任何活動應用程式元件。這種程序存在的唯一原因是做為緩存以改善元件再次于其中運作時的啟動時間。系統經常會殺死這種程序以保持程序緩存和系統核心緩存之間的平衡。
Android會依據程序中目前活躍元件的重要程度來盡可能高的估量一個程序的級别。比如說,如果一個程序中同時有一個服務和一個可視的activity,則程序會被判定為可視程序,而不是服務程序。
此外,一個程序的級别可能會由于其它程序依賴于它而升高。一個為其它程序提供服務的程序級别永遠高于使用它服務的程序。比如說,如果A程序中的内容提供者 為程序B中的用戶端提供服務,或程序A中的服務為程序B中的元件所綁定,則A程序最低也會被視為與程序B擁有同樣的重要性。
本文轉自over140 51CTO部落格,原文連結:http://blog.51cto.com/over140/582308,如需轉載請自行聯系原作者