進(jìn)程和應(yīng)用生命周期
Note : 前臺進(jìn)程 --> 可見進(jìn)程 --> 服務(wù)進(jìn)程 --> 緩存進(jìn)程(原來是五個)
在大多數(shù)情況下,每個 Android 應(yīng)用都在各自的 Linux 進(jìn)程中運行。當(dāng)需要運行應(yīng)用的一些代碼時,系統(tǒng)會為應(yīng)用創(chuàng)建此進(jìn)程,并使其保持運行铐望,直到不再需要它且系統(tǒng)需要回收其內(nèi)存以供其他應(yīng)用使用。
應(yīng)用進(jìn)程的生命周期并不由應(yīng)用本身直接控制,而是由系統(tǒng)綜合多種因素來確定的套蒂,比如系統(tǒng)所知道的正在運行的應(yīng)用部分、這些內(nèi)容對用戶的重要程度茫蛹,以及系統(tǒng)中可用的總內(nèi)存量操刀。這是 Android 非常獨特的一個基本功能。
應(yīng)用開發(fā)者必須了解不同的應(yīng)用組件(特別是 Activity婴洼、Service 和 BroadcastReceiver)對應(yīng)用進(jìn)程的生命周期有何影響骨坑。這些組件使用不當(dāng)會導(dǎo)致系統(tǒng)在應(yīng)用進(jìn)程正執(zhí)行重要任務(wù)時將它終止。
進(jìn)程生命周期錯誤的一個常見示例是當(dāng) BroadcastReceiver 在其 BroadcastReceiver.onReceive() 方法中接收到一個 Intent 時柬采,它會啟動一個線程欢唾,然后從該函數(shù)返回。一旦返回粉捻,則系統(tǒng)會認(rèn)為 BroadcastReceiver 不再處于活動狀態(tài)匈辱,因此不再需要其托管進(jìn)程(除非其中有其他應(yīng)用組件處于活動狀態(tài))。因此杀迹,系統(tǒng)可能會隨時終止進(jìn)程以回收內(nèi)存亡脸,這樣會終止在進(jìn)程中運行的衍生線程押搪。要解決這個問題,通城衬耄可以從 BroadcastReceiver 調(diào)度 JobService大州,這樣系統(tǒng)就知道進(jìn)程中還有處于活動狀態(tài)的任務(wù)正在進(jìn)行中。
為了確定在內(nèi)存不足時應(yīng)該終止哪些進(jìn)程垂谢,Android 會根據(jù)每個進(jìn)程中運行的組件以及這些組件的狀態(tài)厦画,將它們放入“重要性層次結(jié)構(gòu)”。這些進(jìn)程類型包括(按重要性排序):
- 前臺進(jìn)程是用戶目前執(zhí)行操作所需的進(jìn)程滥朱。在不同的情況下根暑,進(jìn)程可能會因為其所包含的各種應(yīng)用組件而被視為前臺進(jìn)程。如果以下任一條件成立徙邻,則進(jìn)程會被認(rèn)為位于前臺:
它正在用戶的互動屏幕上運行一個 Activity(其 onResume() 方法已被調(diào)用)排嫌。
它有一個 BroadcastReceiver 目前正在運行(其 BroadcastReceiver.onReceive() 方法正在執(zhí)行)旱爆。
它有一個 Service 目前正在執(zhí)行其某個回調(diào)(Service.onCreate()撩银、Service.onStart() 或 Service.onDestroy())中的代碼。
系統(tǒng)中只有少數(shù)此類進(jìn)程唤冈,而且除非內(nèi)存過低帅容,導(dǎo)致連這些進(jìn)程都無法繼續(xù)運行颇象,才會在最后一步終止這些進(jìn)程。通常并徘,此時設(shè)備已達(dá)到內(nèi)存分頁狀態(tài)遣钳,因此必須執(zhí)行此操作才能使用戶界面保持響應(yīng)。
- 可見進(jìn)程正在進(jìn)行用戶當(dāng)前知曉的任務(wù)麦乞,因此終止該進(jìn)程會對用戶體驗造成明顯的負(fù)面影響蕴茴。在以下條件下,進(jìn)程將被視為可見:
它正在運行的 Activity 在屏幕上對用戶可見路幸,但不在前臺(其 onPause() 方法已被調(diào)用)荐开。舉例來說,如果前臺 Activity 顯示為一個對話框简肴,而這個對話框允許在其后面看到上一個 Activity晃听,則可能會出現(xiàn)這種情況。
它有一個 Service 正在通過 Service.startForeground()(要求系統(tǒng)將該服務(wù)視為用戶知曉或基本上對用戶可見的服務(wù))作為前臺服務(wù)運行砰识。
系統(tǒng)正在使用其托管的服務(wù)實現(xiàn)用戶知曉的特定功能能扒,例如動態(tài)壁紙、輸入法服務(wù)等辫狼。
相比前臺進(jìn)程初斑,系統(tǒng)中運行的這些進(jìn)程數(shù)量較不受限制,但仍相對受控膨处。這些進(jìn)程被認(rèn)為非常重要见秤,除非系統(tǒng)為了使所有前臺進(jìn)程保持運行而需要終止它們砂竖,否則不會這么做。
-
服務(wù)進(jìn)程包含一個已使用 startService() 方法啟動的 Service鹃答。雖然用戶無法直接看到這些進(jìn)程乎澄,但它們通常正在執(zhí)行用戶關(guān)心的任務(wù)(例如后臺網(wǎng)絡(luò)數(shù)據(jù)上傳或下載),因此系統(tǒng)會始終使此類進(jìn)程保持運行测摔,除非沒有足夠的內(nèi)存來保留所有前臺和可見進(jìn)程置济。
已經(jīng)運行了很長時間(例如 30 分鐘或更長時間)的服務(wù)的重要性可能會降位,以使其進(jìn)程降至下文所述的緩存 LRU 列表锋八。這有助于避免超長時間運行的服務(wù)因內(nèi)存泄露或其他問題占用大量內(nèi)存浙于,進(jìn)而妨礙系統(tǒng)有效利用緩存進(jìn)程。
-
緩存進(jìn)程是目前不需要的進(jìn)程挟纱,因此羞酗,如果其他地方需要內(nèi)存,系統(tǒng)可以根據(jù)需要自由地終止該進(jìn)程樊销。在正常運行的系統(tǒng)中整慎,這些是內(nèi)存管理中涉及的唯一進(jìn)程:運行良好的系統(tǒng)將始終有多個緩存進(jìn)程可用(為了更高效地切換應(yīng)用)脏款,并根據(jù)需要定期終止最早的進(jìn)程围苫。只有在非常危急(且具有不良影響)的情況下,系統(tǒng)中的所有緩存進(jìn)程才會被終止撤师,此時系統(tǒng)必須開始終止服務(wù)進(jìn)程剂府。
這些進(jìn)程通常包含用戶當(dāng)前不可見的一個或多個 Activity 實例(onStop() 方法已被調(diào)用并返回)。只要它們正確實現(xiàn)其 Activity 生命周期(詳情請見 Activity)剃盾,那么當(dāng)系統(tǒng)終止此類流程時腺占,就不會影響用戶返回該應(yīng)用時的體驗,因為當(dāng)關(guān)聯(lián)的 Activity 在新的進(jìn)程中重新創(chuàng)建時痒谴,它可以恢復(fù)之前保存的狀態(tài)衰伯。
這些進(jìn)程保存在偽 LRU 列表中,列表中的最后一個進(jìn)程是為了回收內(nèi)存而終止的第一個進(jìn)程积蔚。此列表的確切排序政策是平臺的實現(xiàn)細(xì)節(jié)意鲸,但它通常會先嘗試保留更多有用的進(jìn)程(比如托管用戶的主屏幕應(yīng)用、用戶最后看到的 Activity 的進(jìn)程等)尽爆,再保留其他類型的進(jìn)程怎顾。還可以針對終止進(jìn)程應(yīng)用其他政策:比如對允許的進(jìn)程數(shù)量的硬限制,對進(jìn)程可持續(xù)保持緩存狀態(tài)的時間長短的限制等漱贱。
在決定如何對進(jìn)程進(jìn)行分類時槐雾,系統(tǒng)會參考進(jìn)程中當(dāng)前活動的所有組件中最重要的級別。請參閱 Activity幅狮、Service 和 BroadcastReceiver 文檔募强,詳細(xì)了解這些組件各自對進(jìn)程的整體生命周期有何影響株灸。每個類的文檔都詳細(xì)介紹了它們對應(yīng)用的整個生命周期有何影響。
進(jìn)程的優(yōu)先級也可能因從屬于進(jìn)程的其他依賴項而提升擎值。例如蚂且,如果進(jìn)程 A 已通過 Context.BIND_AUTO_CREATE 標(biāo)記綁定到 Service,或在使用進(jìn)程 B 中的 ContentProvider幅恋,則進(jìn)程 B 的分類始終至少和進(jìn)程 A 一樣重要杏死。
https://developer.android.com/guide/components/activities/process-lifecycle