喜聞樂見-Android應用的生命周期

来源:https://www.cnblogs.com/holy-loki/archive/2018/10/01/9735131.html
-Advertisement-
Play Games

本文主要講述了App的啟動流程、Application的生命周期以及進程的回收機制。 ...


本文主要講述了App的啟動流程、Application的生命周期以及進程的回收機制。

在絕大多數情況下,每一個Android應用都在自己的Linux進程中運行。當需要運行某些代碼時,進程就會被創建。進程將保持運行直到不再需要,當其他應用有需要的時候,系統會釋放該進程的記憶體。

一個不常見但很基礎的Android特性是,一個應用進程的生命周期並不是由應用本身直接控制的。它是由系統根據正在運行的程式,對用戶的重要程度以及所占用的記憶體,綜合去管理的。

1. App啟動流程

此處討論的是第一次啟動App。在講解App啟動流程的時候,有兩點需要知曉:

  1. 每一個App都運行在一個獨立空間里,也可以稱之為沙盒,這意味著它是在獨立的線程中,擁有自己的虛擬機實例,被分配一個唯一的用戶ID。
  2. App由很多不同組建組成,這些組件還可以調用其他App的組建,並沒有一個單獨的類似於main函數的入口。

總體來說,App啟動分為三個步驟,創建進程、綁定Application以及啟動Activity。當用戶點擊Android桌面一個App圖標,啟動一個應用的時候,整個流程如下所示:

App Launch Summary

點擊事件通過Binder IPC機制最終被轉換成startActivity(intent),而App相關信息的解析以及處理則在安裝的時候就已經完畢。當startActivity的時候,ActivityManagerService(AMS)的操作如下:

  • 第一步是intent解析。通過PackageManager的resolveIntent()方法,收集目標intent對象的信息。
  • 第二步是許可權檢查。通過grantUriPermissionLocked()方法,檢查用戶是否有足夠的許可權去調用intent的目標組件。
  • 第三步是創建新的任務。如果用戶有足夠的許可權,ActivityManagerService就會檢查目標Activity是否需要被載入在新的任務中。這個任務是根據Intent Flag來進行創建的。

最後檢測進程記錄表(ProgressRecord)是否存在。如果不存在,則需要通過ActivityManagerService來創建新的進程。

1.1 進程創建

ActivityManagerService通過調用startProcessLocked()方法來創建一個新的進程,這個方法會通過socket連接發送參數到Zygote進程。Zygote創建ActivityThread對象並返回新創建進程的pid。ActivityThread通過依次調用Looper.prepareLoop()和Looper.loop()方法開啟消息迴圈。

1.2 綁定Application

當進程創建完畢後,需要將其與Application綁定起來。ActivityThread通過發送BIND_APPLICATION消息執行綁定,會執行makeApplication()方法將App的類載入進記憶體。

1.3 啟動Activity

經過前面兩步,系統擁有了與application相關聯的進程,應用中相關的類被載入到進程的記憶體區域。在新創建或者已經存在的進程中啟動Activity的步驟是一樣的。ActivityThread通過發送LAUNCH_ACTIVITY消息進行啟動操作。

大致梳理一下上面的過程,當用戶點擊應用圖標的時候,系統會去檢測進程是否存在,如果不存在,則通過Zygote創建進程,創建完進程後,則需要將進程與App進行綁定,將App的資源載入到記憶體中,當載入完畢,各種條件準備就緒,接下來就是啟動Activity了,如此,App的界面就展示出來了。

2. Application生命周期

此處討論的是Application類,而非應用生命周期。Application的作用,用官方文檔的話說。

Base class for maintaining global application state.

它的作用是維護全局的應用狀態的基類。Application類是應用中最先被初始化的類,先於Activity等組件。它的生命周期與Activity有幾分相似,都經歷了創建銷毀過程,只不過它是一個線性的過程,不存在一些恢復過程。

2.1 onCreate

Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.

當應用啟動的時候調用,除了content providers之外,早於其他任何組件的創建。

2.2 onLowMemory

This is called when the overall system is running low on memory, and actively running processes should trim their memory usage.

當整個系統記憶體不足的時候,活躍的進程需要減少它們的記憶體使用的時候,回調會被調用。系統調用此回調過後,會產生一次GC操作。

2.3 onTerminate

This method is for use in emulated process environments.It will never be called on a production Android device, where processes are removed by simply killing them; no user code (including this callback) is executed when doing so.

在正式環境的真實設備上,不會被調用。由於系統結束進程採用的是kill的方法,因此不會產生相關的回調。

2.4 onTrimMemory

Called when the operating system has determined that it is a good time for a process to trim unneeded memory from its process.

當系統檢測到應用可以回收不需要的記憶體時,會產生此回調。例如應用處於後臺,系統記憶體不足的時候。

3. 回收機制

當系統出現低記憶體狀況的時候,會根據不同進程的優先順序進行記憶體回收。系統根據進程的狀態,將進程分為四個等級。

3.1 Foreground Process

前臺進程是優先順序最高的進程,用戶當前操作交互的必須是前臺進程。當一個進程包含以下條件的時候,可以認為是前臺進程。

  1. 用戶正在交互的,處在屏幕最上層的Activity(onResume被調用過後)。
  2. 包含一個正在運行的BroadcastReceiver(onReceive正在執行)。
  3. 包含一個正在運行它的回調(onCreate、onStart、onDestroy)的service。

在一般狀況下,殺死前臺進程需要用戶交互。當被系統殺死的時候,說明此時系統連該進程所需要的記憶體都無法滿足,是最後才被殺死的。

3.2 Visible Process

可見進程是當前用戶關心但是殺掉它會顯著的影響用戶體驗的進程。當包含如下情況時,該進程可以被當做可見進程。

  1. 包含一個對用戶可見但不在前臺(onPause被調用過後)的Activity。
  2. 包含一個通過startForeground啟動,正在運行的作為前臺service的進程。
  3. 包含一些用戶可感知的特定需求的service,例如動態壁紙、輸入服務等。

可見進程一般不會被銷毀,除非是為了保證所有前臺進程的運行,而不得不殺死可見進程。

3.3 Service Process

服務進程是包含用startService所創建service的進程。這類進程對用戶不是直接可見,但是用戶會關心的,例如後臺上傳服務等等。所以系統會儘量維持它們的運行,除非系統記憶體不足以維持前臺進程和可見進程的運行需要。

當service運行了很長的時間,例如超過30分鐘,系統就會對其降級,以使該進程會被更容易的回收。

3.4 Cached Process

緩存進程是當前不被需要的進程,因此系統可以在任何需要記憶體的時候,釋放掉它們的記憶體。

這類進程通常包含一個或多個當前不可見(onStop被調用)的Activity實例。當系統殺掉這類進程的時候,不會影響用戶的體驗。

3.5 不一致的地方

關於進程優先順序,一般網上給出的前三種跟此處所列一致,不同之處是最後兩種為後臺進程以及空進程,而谷歌文檔上,直接被歸到緩存進程了。這個本身沒有什麼衝突,本質是一樣的,谷歌根據進程對用戶的重要程度劃分的優先順序,記住這個大方向就沒啥問題了。

3.6 管理

關於進程的管理,首先需要知道Low Memory Killer(LMK)這個概念。它是基於Linux的Out of Memory Mechanism(OOM機制)改進而來的。LMK是一個內核層組件,是一個進程殺手。它的主要作用是在系統低記憶體狀態時,釋放掉那些不太重要進程的記憶體,讓系統更加流暢。OOM只有當系統記憶體不足的時候才會啟動檢查,而LMK則不僅是在應用程式分配記憶體發現記憶體不足時啟動檢查,它也會定時地進行檢查。

每一個進程根據其重要性,都包含一個oom_adj值,oom_adj的大小和進程的類型以及進程被調度的次序有關,AMS會去動態的更新oom_adj。當系統處在低記憶體狀態時,LMK會根據oom_adj值大小,去殺死相關的進程。oom_adj值得範圍是-17~15,一個進程的oom_adj值越高,它被殺死的概率就越大。

整個過程就是AMS更新oom_adj值,LMK去挑選並殺死進程。

4. 問題

ActivityManagerService的主要功能包括哪些?

可以看到,在安裝App以及啟動App的過程中,都有AMS的大量參與,它的主要功能包括以下幾部分:

  1. 統一調度各應用程式的Activity
  2. 記憶體管理
  3. 進程管理

App的安裝過程是怎樣的?

Apk其實就是一個壓縮包,系統安裝App的過程,其實就是資源的解析、拷貝以及驗證等過程。

PackageManagerService會將App中的Manifest信息解析出來,並持久化,當用戶點擊桌面icon的時候,系統就會知道該啟動哪個組件。

PMS安裝App,最後底層調用的也是adb命令來執行的。

大致來說,整個流程是,解析apk文件,執行安裝過程,最後更新UI。

onLowMemory與onTrimMemory區別?

onLowMemory與onTrimMemory都是可以進行記憶體回收操作的地方,兩者不同之處有以下幾點:

  1. 兩者API level不同,onLowMemory在API level 1就被添加了,而onTrimMemory是在API level 14中被添加的。當然,對於現在最低版本都是從十幾開始支持的,完全可以直接使用onTrimMemory。
  2. 兩者的觸發時機不同,onLowMemory是在系統出現低記憶體狀況時被觸發,而onTrimMemory則是在置於後臺而記憶體不足時被觸發。

對於API 14以上的條件下,onTrimMemory在TRIM_MEMORY_COMPLETE級別跟onLowMemory可以等同。

5. 參考

  1. Processes and Application Lifecycle
  2. Android Application Launch
  3. Android Application Launch Part 2
  4. Application
  5. Android application and activity life cycle - Tutorial
  6. Android系統APP安裝流程解析
  7. android內核剖析學習筆記:AMS(ActivityManagerService)內部原理和工作機制
  8. Android源碼解析之(十二)-->系統啟動並解析Manifest的流程
  9. Android源碼解析之(十三)-->apk安裝流程
  10. How Android manages background processes?
  11. Android Low Memory Killer
  12. Android low memory killer 機制
  13. How to Tweak Android Low Memory Killer to Your Needs

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 【原創,轉載請註明出處】 應屆生小祖參加了個需求分析會回來後跟我說被產品懟了一句: "不就是寫SQL嗎,要那麼久嗎" 我去,欺負我小弟,這我肯定不能忍呀,於是我寫了一篇文章發在了公司的wiki 貼出來給大家看看,省略了一些敏感的內容。當然內部版言辭也會溫和一點,嘻嘻 在哪裡寫SQL? 這個問題高級點 ...
  • 用PowerDesigner比較直觀, 方便管理,修改資料庫,分享 Oracle的逆向工程,和模型圖的顯示設置 Oracle 為32位的,64位的Oracle PowerDesigner新版本支持,但是搞不到破解碼... https://blog.csdn.net/u011781521/articl ...
  • oracle10g以上支持正則表達式的函數主要有下麵四個:1、REGEXP_LIKE :與LIKE的功能相似2、REGEXP_INSTR :與INSTR的功能相似3、REGEXP_SUBSTR :與SUBSTR的功能相似4、REGEXP_REPLACE :與REPLACE的功能相似POSIX 正則表 ...
  • 一. xtrabackup 選項說明 在操作xtrabackup備份與恢復之前,先看下該工具的選項,下麵記錄了xtrabackup二進位文件的部分命令行選項,後期把常用的選項在補上。點擊查看xtrabackup Option 指南 選項名 說明 --apply-log-only 僅在準備備份時,執行 ...
  • like 用法介紹: 1、“_”:匹配單個任意字元 select * from bqh3 where name like '_崔'; 2、“%”:匹配0個或多個任意字元。但有三種情況如下: like %關鍵字:以關鍵字開頭的記錄 like 關鍵字%:以關鍵字結尾的記錄 like %關鍵字% :包含以 ...
  • 本文介紹了熱門的NoSQL資料庫MongoDB的副本集這種分散式架構的一些概念和操作。主要內容包括: MongoDB副本集相關概念 MongoDB副本集環境搭建 MongoDB副本集的讀寫分離 MongoDB副本集的故障轉移 MongoDB副本集的優點 MongoDB副本集的缺點 1.副本集相關概念 ...
  • 本文列舉了項目開發使用Flutter會遇到的問題,以及如何使用Flutter module在現有項目中集成Flutter,並對其原理進行了分析。 ...
  • launchMode,通俗點說,就是定義了Activity應該如何被launch的。那麼這幾種模式的區別以及應用場景,會有何不同呢?谷歌是基於什麼原因設計這幾種模式的呢?這幾種模式背後的工作原理是什麼呢? ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...