1. 程式人生 > >Android程序和應用生命週期

Android程序和應用生命週期

在大多數情況下,每個Android應用程式都執行在它自己所在的Linux程序中。這個程序在應用執行起來的時候被建立,而且將會存活到這個應用不再被使用或者系統記憶體不足需要回收掉該應用的記憶體空間以供其他應用使用。

Android的一個基本特性就是應用的程序的存活時間不是受應用直接控制的。而是通過系統對所有正在執行的應用的多個方面進行比對,究竟哪些對使用者來說是重要的,以及系統中可用的記憶體是多少決定的。

開發者必須瞭解應用中不同的元件(尤其是Activity,Service,BroadcastReceiver)對應用的程序存活所造成的影響。如果不是以正確的使用方式使用這些元件,將會在應用做重要工作時被系統所終結(kill)。

一個典型的錯誤使用例子就是BroadcastReceiver的onReceive方法中啟動一個執行緒。而當BroadcastReceiver接收到相應的廣播且返回onReceive方法時這個BroadcastReceiver就不處在活躍狀態了(no longer active),那麼這個BroadcastReceiver所在的程序就不再被需要了(除非還有應用的其他元件執行在這個程序中)。所以系統隨時能終結(kill)這個程序去回收這塊記憶體,而當這種情況出現時,在BroadcastReceiver中啟動的執行緒也將被終止。為了避免這種情況的出現建議在BroadcastReceiver中使用JobService,這樣系統就知道這個程序還在處理重要的工作。

為了決定在低記憶體的情況下哪個程序終結哪個程序,Android系統中通過程序中執行的元件和他們的狀態進行”重要程度分級“(importance hierarchy)。而通過這些等級劃分來進行系統對各程序的終結順序(排序按重要-次要劃分):

  1. 前臺程序(foreground process):當前正在螢幕上執行,使用者正在互動的程序。多種不同的應用程式元件可以實現當前程序為前臺程序。當出現以下任意一種情況時系統都將視該程序為前臺程序:

    • 使用者正在對螢幕上的活動(Activity)進行互動(當Activity的onResume()方法被呼叫到之後出現的情況)
    • 當前程序中有BroadcastReceiver正在執行時(當BroadcastReceiver.onReceive()方法正在被執行的情況)
    • 當前程序中有Service正執行其回撥方法時(Service.onCreate(), Service.onStart(), or Service.onDestroy()被呼叫)
      系統中始終只會有少數這樣的程序,而且這些程序只有在記憶體不足以支援這些程序繼續執行的時才會被終結。通常只有在裝置的記憶體已經接近使用完時才會終結這些程序以保持使用者介面的響應。
  2. 可見程序(visible process):可見程序指使用者能夠觀察到正在執行的程序。所以當終結這些程序時可能會對使用者體驗造成不良影響。當出現以下情況我們視該程序為可見程序:

    • 當前程序正在螢幕上執行一個可見的Activity,但是該Activity不處於前臺狀態(呼叫了onPause()方法)。比如這個Activity彈出了一個dialog,那麼這個Activity所在的程序就被稱為可見程序。
    • 當前程序中正在執行通過Service.starForeground()啟動的前臺Service。
    • 當前程序正持有一個能被使用者感知的擁有特定特徵的服務,比如動態桌布,輸入法服務等。
      系統中執行的這些程序的數量少於前臺程序。這些程序被認為是非常重要的,不會被終結,除非這樣做是為了保持所有前臺程序執行。
  3. 服務程序(service process):服務程序指的是當前程序中有通過startService()方法啟動的服務。雖然這些程序對使用者來說並不可見,但是這些程序還是在做著使用者所關心的事(比如在後臺進行上傳或者下載的工作),所以系統會保證這些程序的執行除非系統記憶體不足以支援前臺程序和可見程序的執行。
    已經運行了很長一段時間的服務(如30分鐘以上)可能會將其重要程度降級。這是為了避免出現長時間執行服務時的記憶體洩漏或者為了保證系統有效地使用快取程序問題以致於消耗了太多記憶體的情況。

    以上的翻譯有點生硬,為了避免翻譯出錯放入原文:This helps avoid situations where very long running services with memory leaks or other problems consume so much RAM that they prevent the system from making effective use of cached processes.

  4. 快取程序(cached process):快取程序指的是當前並不需要的程序,系統可以在其他程式需要記憶體時隨時將該程序終結。一個正常執行的系統中會有多個快取程序可用(為了有效地進行應用間的切換)

    以上翻譯並不完全,因為本人也不是很理解原文的意思,所以只翻譯了一部分,想要了解更多請看原文。

這些程序通常持有一個或多個不可見的Activity例項(呼叫了onStop()方法)。當我們正確地實現了這些Activity的生命週期,那麼當系統終結了這些程序並不會對使用者體驗造成影響:Activity在新程序中被recreate時,Activity可以恢復之前儲存的狀態。(通過onSaveInstanceState方法和onRestoreInstanceState()方法恢復)。

這些快取程序被儲存在pseudo-LRU列表中,這個列表會在需要回收記憶體時將列表中最後一個程序終結。這個列表中的排序策略是根據平臺的不同實現細節來安排,但是通常來說它會盡可能多地去保留有用的程序(比如在使用者介面執行的應用,使用者最後看到的一個Activity等),而不是保留其他型別的程序。還有一些其他的終結程序的策略可能被應用,比如:對程序數量的控制、程序可以持續快取的時間限制等等。

系統會將所有元件活躍的程序按照重要程度進行歸類。關於組建對程序的生命週期影響具體參考Activity,Service和BroadcastReceiver文件。

一個程序的優先順序有可能會被與之關聯的程序的優先順序所提高。舉個例子,如果程序A在程序B中通過Context.BIND_AUTO_CREATE去綁定了一個Service或者正在呼叫ContentProvider,那麼程序B的優先順序至少就跟程序A的優先順序一樣高。