Android 程序和應用的生命週期
程序和應用的生命週期
多數情況下,應用執行在他自己的Linux程序裡。當需要執行程式碼時,系統為應用程式分配一個程序,應用一直執行在該程序裡,一直到不再需要了,系統重新收回這部分記憶體供其它應用使用。
Android中一個特殊的地方在於應用程序的生命週期不完全由應用自己控制。而是系統通過正在執行的所有應用經過整合,例如該應用對使用者來說有多重要,還剩多少記憶體等決定應用的生命週期。
直到每個元件(Activity,Service,BroadcastReceiver,Contentprovider)是如何影響應用生命週期很重要。元件的錯誤使用可能引起系統殺死正在執行重要程式碼的應用程序。
一個程序生命週期典型的bug就是BroadcastReceiver在他的onReceive()方法中收到一個intent,然後啟動一個執行緒執行任務,然後返回。一旦返回,系統就認為BroadcastReceiver已經不再需要,他所在的程序也不需要了(除非程序裡還有其它應用元件)。所以,系統隨時可能收回程序,釋放記憶體,同時把程序裡的執行緒也關掉了。解決辦法就是啟動一個JobService,這樣系統知道程序裡還有活動的工作。
低記憶體時殺掉哪個應用,Android基於元件及其狀態把每個程序都劃分了重要性優先順序。程序優先順序有:
1、前臺程序是使用者正在使用的程序。各種元件都能以不同的方式使其所在程序成為前臺程序。下面任何一種情況都是程序進入前臺程序:
- 使用者正在互動的顯示在螢幕最上方的Activity(onResume()方法被呼叫了)。
- BroadcastReceiver正在執行(BroadcastReceiver.onReceive()方法正在執行)。
- Service正在執行回撥(Service.onCreate(),Service.onStart()或者Service.onDestroy())。
這種程序只會存在幾個,如果記憶體低,他們會最後被殺掉。這種情況下,一般儲存器正在執行換頁操作,以保證裝置和使用者互動。
2、可見程序執行的工作對使用者來說是可感知的,所以如果殺掉這種程序,會產生不好的使用者體驗。下面幾種情況屬於可見程序。
- 程式正在執行Activity,Activity可見但不在前臺(onPause()已經被呼叫)。例如,前臺應用顯示為Dialog,Dialog後面的Activity所在的程序即為可見程序。
- 通過Service.startForegroundService()啟動的服務,服務正在執行的程序。
- 使用者可感知的特殊服務正在使用的服務所在的程序,例如動態桌布,輸入法服務等。
這種程序的數量比前臺程序控制的少些,但是也是有所控制的。這些程序被認為是很重要的程序,一般不會被殺,除非前臺程序不能運行了。
3、服務程序中有一個通過startSerivce()呼叫起來的服務。儘管這些程序使用者不可見,但是他們執行一些對使用者來說很重要的任務(後臺上傳,下載資料),系統會一直保持這些程序,除非前臺程序和可見程序不能執行了。
運行了很長時間(30分鐘)的服務重要性可能會被降級,降到的緩衝程序。這樣可以避免一些長期執行的服務,帶有記憶體洩露或者其他問題,消耗了太多記憶體,使得緩衝程序的效果變差。
4、緩衝程序即不再需要的程序,如果其他地方需要記憶體,系統隨時可以回收他們。在一個正常行為系統中,這種程序是包含在記憶體管理中的程序:一個好的執行系統總是有多個緩衝程序(為了更有效的在程序之間切換)並定期殺掉最老的緩衝程序。只有在非常嚴重(不方便)的時候,才會殺掉所有緩衝程序,並且開始殺服務程序。
這些程序通常持有一個或多個使用者不可見(onStop()方法已經被呼叫並返回)的Activity例項。假如正確實現了Activity的生命週期,系統殺掉該程序並不會影響到使用者體驗。當用戶重新進入該應用時:在新的程序中重新建立時,Activity可以恢復之前儲存的狀態。
這些程序儲存在偽LRU列表中,列表中最後的程序是回收記憶體最先被殺掉的。具體實現是在平臺中,但是總的來說,測略是保護更加重要的程序(一個儲存home應用,最早看到的Activity)。其它殺程序策略同樣適用:程序數量,程序在緩衝區最長時間等。
當決定程序的重要性時,系統根據最重要的元件決定其所在程序的重要級別。各元件文件中更加詳細的描述了其對程序重要性的影響。
如果其他程序依賴該程序,被依賴的程序重要性有可能會被提高。例如,程序A通過Context.BIND_AUTO_START繫結一個B程序的服務或者用B程序的ContentProvider,那麼B程序優先順序不低於A。