Activity 的 36 大難點,你會幾個?「建議收藏」

  • 2019 年 10 月 30 日
  • 筆記

Android

前言

Android 有一段時間了,一直都只顧著學新的東西,最近發現很多平常用的少的東西竟讓都忘了,趁著這兩天,打算把有關 Activity 的內容以問題的形式梳理出來,也供大家查缺補漏。

本文中,我將一改往日寫部落格的習慣,全文用 XMind 將所有知識點以思維導圖的形式呈現,歡迎大家食用~~

# 文章目錄

文章目錄

方便大家學習,我在 GitHub 上建立個 倉庫


# 神圖

  • 在開始之前,先讓我們看看 Androidactivity 到底都有哪些東西?
  • 借一張網上很火的圖帶你了解 Activity

一張圖帶你了解 Activity

# 1. 生命周期

  • 先貼一張聞名遐邇的圖
  • 我們生命周期先看看具體有哪些方法回調,在逐一攻破:

生命周期

1.1 Dialog 彈出時

dialog彈出時

  • 如果是單純是創建的 dialogActivity 並不會執行生命周期的方法
  • 但是如果是跳轉到一個不是全螢幕的 Activity 的話, 當然就是按照正常的生命周期來執行了
  • onPasue() -> onStop()

1.2 橫豎屏切換時

橫豎屏切換時

  • 不設置 Activityandroid:configChanges 時,切屏會重新調用各個生命周期,切橫屏時會執行一次,切豎屏時會執行兩次
  • 設置 Activityandroid:configChanges="orientation" 時,切屏還是會重新調用各個生命周期,切橫、豎屏時只會執行一次
  • 設置 Activityandroid:configChanges="orientation|keyboardHidden" 時,切屏不會重新調用各個生命周期,只會執行 onConfigurationChanged 方法
  • 注意:還有一點,非常重要,一個 Android 的變更細節!當 API >12 時,需要加入 screenSize 屬性,否則螢幕切換時即使你設置了 orientation 系統也會重建 Activity

橫豎屏切換生命周期的執行

1.3 不同場景下 Activity 生命周期的變化過程

不同場景下Activity生命周期的變化過程

  • 啟動 ActivityonCreate() —> onStart() —> onResume()Activity 進入運行狀態。
  • 鎖定屏與解鎖螢幕:只會調用 onPause() ,而不會調用 onStop 方法,開屏後則調用 onResume()

已啟動的 Activity 生命周期的變化

  • Activity 退居後台: 當前 Activity 轉到新的 Activity 介面或按 Home 鍵回到主屏: onPause() —> onStop() ,進入停滯狀態。
  • Activity 返回前台: onRestart() —> onStart() —> onResume() ,再次回到運行狀態。
  • Activity 退居後台: 且系統記憶體不足, 系統會殺死這個後台狀態的 Activity ,若再次回到這個 Activity ,則會走 onCreate() –> onStart() —> onResume()

1.4 將一個 Activity 設置成窗口的樣式

設置 Activity 成窗口樣式

只需要給我們的 Activity 配置如下屬性即可。
android:theme="@android:style/Theme.Dialog"

1.5 退出已調用多個 Activity 的 Application

  • 通常情況用戶退出一個 Activity 只需按返回鍵,我們寫程式碼想退出 activity 直接調用 finish() 方法就行。

退出調用多個 Activity 的 Application

  • 發送特定廣播:
  1. 在需要結束應用時, 發送一個特定的廣播,每個 Activity 收到廣播後,關閉 即可。
  2. 給某個 activity 註冊接受接受廣播的意圖 registerReceiver(receiver, filter)
  3. 如果過接受到的是 關閉 activity 的廣播 activity finish()
  • 遞歸退出
  1. 就調用 finish() 方法 把當前的 Activity 退出
  2. 在打開新的 Activity 時使用 startActivityForResult , 然後自己加標誌, 在 onActivityResult 中處理, 遞歸關閉。
  • 其實
  1. 也可以通過 intentflag 來實現 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) 激活一個新的 activity
  2. 此時如果該任務棧中已經有該 Activity , 那麼系統會把這個 Activity 上面的所有 Activity 幹掉。
  3. 其實相當於給 Activity 配置的啟動模式為 SingleTop
  • 記錄打開的 Activity
  1. 每打開一個 Activity , 就記錄下來。
  2. 在需要退出時 , 關閉每一個 Activity

1.6 鎖定屏與解鎖螢幕,Activity 如何執行生命周期

鎖定屏與解鎖螢幕,Activity如何執行生命周期

  • 只會調用 onPause() ,而不會調用 onStop 方法,開屏後則調用 onResume()

1.7 修改 Activity 進入和退齣動畫

修改 Activity 進入和退齣動畫

  • 可以通過兩種方式 , 一是通過定義 Activity 的主題 ,二是通過覆寫 ActivityoverridePendingTransition 方法。
  • 通過設置主題樣式在 styles.xml 中編輯程式碼 , 添加 themes.xml 文件:在 AndroidManifest.xml 中給指定的 Activity 指定 theme
  • 覆寫 overridePendingTransition 方法:overridePendingTransition(R.anim.fade, R.anim.hold);

1.8 Activity 的四種狀態

四種狀態

  • runnig :用戶可以點擊,activity 處於棧頂狀態。
  • pausedactivity 失去焦點的時候,被一個非全螢幕的 activity 佔據或者被一個透明的 activity 覆蓋,這個狀態的 activity 並沒有銷毀,它所有的狀態資訊和成員變數仍然存在,只是不能夠被點擊。(記憶體緊張的情況,這個 activity 有可能被回收)

關閉

  • stopped :這個 activity 被另外一個 activity 完全覆蓋,但是這個 activity 的所有狀態資訊和成員變數仍然存在(除了記憶體緊張)
  • killed :這個 activity 已經被銷毀,其所有的狀態資訊和成員變數已經不存在了。

1.9 如何處理異常退出

如何處理異常退出

  • Activity 異常退出的時候 –> onPause() –> onSaveInstanceState() –> onStop() –> onDestory()
  • 需要注意的是 onSaveInstanceState() 方法與 onPause 並沒有嚴格的先後關係,有可能在 onPause 之前,也有可能在其後面調用,但會在 onStop() 方法之前調用
  • 異常退出後又重新啟動該 Activity –> onCreate() –> onStart() –> onRestoreInstanceState() –> onResume()

異常退出後又重新啟動

  • 搞懂這個生命周期的執行後就可以回答了,首先要知道面試官的意思:是要重新啟動並恢復這個 Activity 還是說直接退出整個 app
  • 如果要恢復則要在 onSaveInstanceState() 中進行保存數據並在 onRestoreInstanceState() 中進行恢復
  • 如果是要退出 app 的話就要捕獲全局的異常資訊,並退出 app
  • 當然個人建議是使用 UncaughtExceotionHandler 來捕獲全局異常進行退出 app 的操作,這樣會減少之前崩潰所造成的後遺症!

1.10 什麼是 onNewIntent

onNewIntent

  • 如果 IntentActivity 處於任務棧的頂端,也就是說之前打開過的 Activity ,現在處於 onPauseonStop 狀態的話,其他應用再發送 Intent 的話

  • 執行順序為:onNewIntentonRestartonStartonResume

2. 啟動模式


2.1 啟動模式

啟動模式

  • Activity 一共有四種 launchModestandardsingleTopsingleTasksingleInstance

Standard

  • Standard 模式(默認模式)
  1. 說明: 每次啟動一個 Activity 都會又一次創建一個新的實例入棧,無論這個實例是否存在。

  2. 生命周期:每次被創建的實例 Activity 的生命周期符合典型情況,它的 onCreateonStartonResume 都會被調用。

  3. 舉例:此時 Activity 棧中以此有 ABC 三個 Activity ,此時C處於棧頂,啟動模式為 Standard 模式。若在 C Activity 中加入點擊事件,須要跳轉到還有一個同類型的 C Activity 。結果是還有一個 C Activity 進入棧中,成為棧頂。

SingleTop

  • SingleTop 模式(棧頂復用模式)
  1. 說明:分兩種處理情況:須要創建的 Activity 已經處於棧頂時,此時會直接復用棧頂的 Activity 。不會再創建新的 Activity ;若須要創建的 Activity 不處於棧頂,此時會又一次創建一個新的 Activity 入棧,同 Standard 模式一樣。

  2. 生命周期:若情況一中棧頂的 Activity 被直接復用時,它的 onCreateonStart 不會被系統調用,由於它並沒有發生改變。可是一個新的方法 onNewIntent 會被回調( Activity 被正常創建時不會回調此方法)。

  3. 舉例:此時 Activity 棧中以此有 ABC 三個 Activity ,此時 C 處於棧頂,啟動模式為 SingleTop 模式。情況一:在 C Activity 中加入點擊事件,須要跳轉到還有一個同類型的 C Activity 。結果是直接復用棧頂的 C Activity。情況二:在 C Activity 中加入點擊事件,須要跳轉到還有一個 A Activity。結果是創建一個新的 Activity 入棧。成為棧頂。

SingleTask

  • SingleTask 模式(棧內復用模式)
  1. 說明:若須要創建的 Activity 已經處於棧中時,此時不會創建新的 Activity ,而是將存在棧中的 Activity 上面的其他 Activity 所有銷毀,使它成為棧頂。

  2. 如果是在別的應用程式中啟動它,則會新建一個 task ,並在該task中啟動這個 ActivitysingleTask 允許別的 Activity 與其在一個 task 中共存,也就是說,如果我在這個 singleTask 的實例中再打開新的 Activity ,這個新的 Activity 還是會在 singleTask 的實例的 task 中。

  3. 生命周期:同 SingleTop 模式中的情況一同樣。僅僅會又一次回調 Activity 中的 onNewIntent 方法

  4. 舉例:此時 Activity 棧中以此有 ABC 三個 Activity 。此時 C 處於棧頂,啟動模式為 SingleTask 模式。情況一:在 C Activity 中加入點擊事件,須要跳轉到還有一個同類型的 C Activity 。結果是直接用棧頂的 C Activity 。情況二:在 C Activity 中加入點擊事件,須要跳轉到還有一個 A Activity 。結果是將 A Activity 上面的 BC 所有銷毀,使 A Activity 成為棧頂。

ingleInstance

  • SingleInstance 模式(單實例模式)
  1. 說明: SingleInstance 比較特殊,是全局單例模式,是一種加強的 SingleTask 模式。它除了具有它所有特性外,還加強了一點:只有一個實例,並且這個實例獨立運行在一個 task 中,這個 task 只有這個實例,不允許有別的 Activity 存在。

  2. 這個經常使用於系統中的應用,比如 Launch 、鎖屏鍵的應用等等,整個系統中僅僅有一個!所以在我們的應用中一般不會用到。了解就可以。

  3. 舉例:比方 A Activity 是該模式,啟動 A 後。系統會為它創建一個單獨的任務棧,由於棧內復用的特性。興許的請求均不會創建新的 Activity ,除非這個獨特的任務棧被系統銷毀。

2.2 啟動模式的使用方式

啟動模式的使用方式

  • Manifest.xml 中指定 Activity 啟動模式
  1. 一種靜態的指定方法
  2. Manifest.xml 文件里聲明 Activity 的同一時候指定它的啟動模式
  3. 這樣在程式碼中跳轉時會依照指定的模式來創建 Activity
  • 啟動 Activity 時。在 Intent 中指定啟動模式去創建 Activity
  1. 一種動態的啟動模式
  2. new 一個 Intent
  3. 通過 IntentaddFlags 方法去動態指定一個啟動模式。
  • 注意:以上兩種方式都能夠為 Activity 指定啟動模式,可是二者還是有差別的。
  1. 優先順序:動態指定方式即另外一種比第一種優先順序要高,若兩者同一時候存在,以另外一種方式為準。

  2. 限定範圍:第一種方式無法為 Activity 直接指定 FLAG_ACTIVITY_CLEAR_TOP 標識,另外一種方式無法為 Activity 指定 singleInstance 模式。

2.3 啟動模式的實際應用場景

這四種模式中的 Standard 模式是最普通的一種,沒有什麼特別注意。而 SingleInstance 模式是整個系統的單例模式,在我們的應用中一般不會應用到。所以,這裡就具體解說 SingleTopSingleTask 模式的運用場景:

啟動模式的實際應用場景

  • SingleTask 模式的運用場景
  1. 最常見的應用場景就是保持我們應用開啟後僅僅有一個 Activity 的實例。
  2. 最典型的樣例就是應用中展示的主頁( Home 頁)。
  3. 假設用戶在主頁跳轉到其他頁面,運行多次操作後想返回到主頁,假設不使用 SingleTask 模式,在點擊返回的過程中會多次看到主頁,這明顯就是設計不合理了。
  • SingleTop 模式的運用場景
  1. 假設你在當前的 Activity 中又要啟動同類型的 Activity
  2. 此時建議將此類型 Activity 的啟動模式指定為 SingleTop ,能夠降低Activity的創建,節省記憶體!
  • 注意:復用 Activity 時的生命周期回調
  1. 這裡還須要考慮一個 Activity 跳轉時攜帶頁面參數的問題。
  2. 由於當一個 Activity 設置了 SingleTop 或者 SingleTask 模式後,跳轉此 Activity 出現復用原有 Activity 的情況時,此 ActivityonCreate 方法將不會再次運行。onCreate 方法僅僅會在第一次創建 Activity 時被運行。
  3. 而一般 onCreate 方法中會進行該頁面的數據初始化、UI 初始化,假設頁面的展示數據無關頁面跳轉傳遞的參數,則不必操心此問題
  4. 若頁面展示的數據就是通過 getInten() 方法來獲取,那麼問題就會出現:getInten() 獲取的一直都是老數據,根本無法接收跳轉時傳送的新數據!
  • 以下,通過一個樣例來具體解釋:

圖片描述

  • 以上程式碼中的 CourseDetailActivity 在配置文件里設置了啟動模式是 SingleTop 模式,依據上面啟動模式的介紹可得知,當 CourseDetailActivity 處於棧頂時。
  • 再次跳轉頁面到 CourseDetailActivity 時會直接復用原有的 Activity ,並且此頁面須要展示的數據是從 getIntent() 方法得來,可是 initData() 方法不會再次被調用,此時頁面就無法顯示新的數據。

  • 當然這樣的情況系統早就為我們想過了,這時我們須要另外一個回調 onNewIntent(Intent intent)方法。此方法會傳入最新的 intent ,這樣我們就能夠解決上述問題。這裡建議的方法是又一次去 setIntent 。然後又一次去初始化數據和 UI 。程式碼例如以下所看到的:

圖片描述

  • 這樣,在一個頁面中能夠反覆跳轉並顯示不同的內容。

2.4 快速啟動一個 Activity

快速啟動一個 Activity

  • 這個問題其實也是比較簡單的,就是不要在 ActivityonCreate 方法中執行過多繁重的操作,並且在 onPasue 方法中同樣不能做過多的耗時操作。

2.5 啟動流程

2.6 Activity 的 Flags

Activity 的 Flags

  • 標記位既能夠設定Activity的啟動模式,如同上面介紹的,在動態指定啟動模式,比方 FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_SINGLE_TOP 等。它還能夠影響 Activity 的運行狀態 ,比方 FLAG_ACTIVITY_CLEAN_TOPFLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 等。

  • 以下介紹幾個基本的標記位,切勿死記,理解幾個就可以,須要時再查官方文檔。

幾個基本的標記位

  • FLAG_ACTIVITY_NEW_TASK
  1. 作用是為 Activity 指定 「SingleTask」 啟動模式。跟在 AndroidMainfest.xml 指定效果同樣
  • FLAG_ACTIVITY_SINGLE_TOP
  1. 作用是為 Activity 指定 「SingleTop」 啟動模式,跟在 AndroidMainfest.xml 指定效果同樣。
  • FLAG_ACTIVITY_CLEAN_TOP
  1. 具有此標記位的 Activity ,啟動時會將與該 Activity 在同一任務棧的其他 Activity 出棧。
  2. 一般與 SingleTask 啟動模式一起出現。
  3. 它會完畢 SingleTask 的作用。
  4. 但事實上 SingleTask 啟動模式默認具有此標記位的作用
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
  1. 具有此標記位的 Activity 不會出如今歷史 Activity 的列表中
  2. 使用場景:當某些情況下我們不希望用戶通過歷史列表回到 Activity 時,此標記位便體現了它的效果。
  3. 它等同於在 xml 中指定 Activity 的屬性.

2.7 onNewInstent()方法什麼時候執行

onNewInstent()方法什麼時候執行

這個是啟動模式中的了,當此 Activity 的實例已經存在,並且此時的啟動模式為 SingleTaskSingleInstance ,另外當這個實例位於棧頂且啟動模式為 SingleTop 時也會觸發 onNewInstent()

# 3. 數據

3.1 Activity 間通過 Intent 傳遞數據大小限制

Activity 間通過 Intent 傳遞數據大小限制

  • Intent 在傳遞數據時是有大小限制的,這裡官方並未詳細說明,不過通過實驗的方法可以測出數據應該被限制在 1MB 之內( 1024KB
  • 我們採用傳遞 Bitmap 的方法,發現當圖片大小超過 1024(準確地說是 1020 左右)的時候,程式就會出現閃退、停止運行等異常(不同的手機反應不同)
  • 因此可以判斷 Intent 的傳輸容量在 1MB 之內。

3.2 記憶體不足時系統會殺掉後台的Activity,若需要進行一些臨時狀態的保存,在哪個方法進行

onSaveInstanceState()

  • ActivityonSaveInstanceState()onRestoreInstanceState() 並不是生命周期方法,它們不同於 onCreate()onPause() 等生命周期方法,它們並不一定會被觸發。

  • onSaveInstanceState() 方法,當應用遇到意外情況(如:記憶體不足、用戶直接按 Home 鍵)由系統銷毀一個 ActivityonSaveInstanceState() 會被調用。
  • 但是當用戶主動去銷毀一個 Activity 時,例如在應用中按返回鍵,onSaveInstanceState() 就不會被調用。
  • 除非該 activity 不是被用戶主動銷毀的,通常 onSaveInstanceState() 只適合用於保存一些臨時性的狀態,而 onPause() 適合用於數據的持久化保存。

3.3 onSaveInstanceState() 被執行的場景

onSaveInstanceState() 被執行的場景

  • 系統不知道你按下 HOME 後要運行多少其他的程式,自然也不知道 activity A 是否會被銷毀
  • 因此系統都會調用 onSaveInstanceState() ,讓用戶有機會保存某些非永久性的數據。以下幾種情況的分析都遵循該原則:
  1. 當用戶按下 HOME 鍵時
  2. 長按 HOME 鍵,選擇運行其他的程式時
  3. 鎖屏時
  4. activity A 中啟動一個新的 activity
  5. 螢幕方向切換時

3.4 兩個 Activity 之間跳轉時必然會執行的方法

兩個 Activity 之間跳轉時必然會執行的方法

一般情況下比如說有兩個 activity , 分別叫 A , B ,當在 A 裡面激活 B 組件的時候, A 會調用 onPause() 方法,然後 B 調用 onCreate() , onStart() , onResume()

這個時候 B 覆蓋了窗體, A 會調用 onStop() 方法. 如果 B 是個透明的,或者 是對話框的樣式, 就不會調用 AonStop() 方法。

3.5 用 Intent 去啟動一個Activity 之外的方法

用 Intent 去啟動一個Activity 之外的方法

  • 使用 adb shell am 命令
  1. am 啟動一個 activity
  2. adb shell am start com.example.fuchenxuan/.MainActivity
  3. am 發送一個廣播,使用 action
  4. adb shell am broadcast -a magcomm.action.TOUCH_LETTER

3.6 scheme 跳轉協議

scheme跳轉協議

3.6.1 定義

定義

  • 伺服器可以訂製化跳轉 app 頁面

  • app 可以通過 Scheme 跳轉到另一個 app 頁面

  • 可以通過 h5 頁面跳轉 app 原生頁面

3.6.2 協議格式:

協議格式

協議格式

  • qh 代表 Scheme 協議名稱

  • test 代表 Scheme 作用的地址域

  • 8080 代表改路徑的埠號

  • /goods 代表的是指定頁面(路徑)

  • goodsIdname 代表傳遞的兩個參數

3.6.3 Scheme使用

  • 定義一個 Scheme

  • 獲取 Scheme 跳轉的參數

  • 調用方式
  1. 原生調用

  1. html調用

  1. 判斷某個Scheme是否有效

# 4. Context

4.1 Context , Activity , Appliction 的區別

Context, Activity, Appliction 的區別

  • 相同:ActivityApplication 都是 Context 的子類。
  • Context 從字面上理解就是上下文的意思, 在實際應用中它也確實是起到了管理 上下文環境中各個參數和變數的總用, 方便我們可以簡單的訪問到各種資源。
  • 不同:維護的生命周期不同。Context 維護的是當前的 Activity 的生命周期, Application 維護的是整個項目的生命周期。
  • 使用 context 的時候, 小心記憶體泄露, 防止記憶體泄露

4.2 Context 是什麼

Context 是什麼

  • 它描述的是一個應用程式環境的資訊,即上下文。

  • 該類是一個抽象( abstract class )類, Android 提供了該抽象類的具體實 現類( ContextIml )。

  • 通過它我們可以獲取應用程式的資源和類, 也包括一些應用級別操作, 例如:啟動一個 Activity ,發送廣播,接受 Intent ,資訊,等。

4.2.1 附加一張 Context 繼承關係圖

Context繼承關係圖

4.3 獲取當前螢幕 Activity 的對象

獲取當前螢幕Activity的對象

4.4 Activity 的管理機制

Activity的管理機制

  1. 什麼是 ActivityRecord
  2. 什麼是 TaskRecord
  3. 什麼是 ActivityManagerService

4.5 什麼是 Activity

什麼是 Activity

  • 四大組件之一,通常一個用戶交互介面對應一個 activity
  • activityContext 的子類,同時實現了 window.callbackkeyevent.callback ,可以處理與窗體用戶交互的事件。
  • 開發中常用的有 FragmentActivityListActivityTabActivityAndroid 4.0Fragment 取代)

# 5. 進程

5.1 Android 進程優先順序

  • 前台 / 可見 / 服務 / 後台 / 空

前台 / 可見 / 服務 / 後台 / 空

5.1.1 前台進程:Foreground process

前台進程:Foreground process

  • 用戶正在交互的 ActivityonResume()
  • 當某個 Service 綁定正在交互的 Activity
  • 被主動調用為前台 ServicestartForeground()
  • 組件正在執行生命周期的回調( onCreate()onStart()onDestory()
  • BroadcastReceiver 正在執行 onReceive()

5.1.2 可見進程:Visible process

可見進程:Visible process

  • 我們的 Activity 處在 onPause()(沒有進入 onStop()
  • 綁定到前台 ActivityService

5.1.3 服務進程:Service process

服務進程

  • 簡單的 startService() 啟動。

5.1.4 後台進程:Background process

後台進程:Background process

  • 對用戶沒有直接影響的進程 — Activity 處於 onStop() 的時候。
  • android:process=":xxx"

5.1.5 空進程:Empty process

空進程:Empty process

  • 不含有任何的活動的組件。( Android 設計的,處於快取的目的,為了第二次啟動更快,採取的一個權衡)

5.2 可見進程

可見進程

可見進程指部分程式介面能夠被用戶看見,卻不在前台與用戶交互的進程。例如,我們在一個介面上彈出一個對話框(該對話框是一個新的 Activity ),那麼在對話框後面的原介面是可見的,但是並沒有與用戶進行交互,那麼原介面就是可見進程。

  • 一個進程滿足下面任何一個條件都被認為是可視的:
  1. 寄宿著一個不是前台的活動,但是它對用戶仍可見(它的 onPause() 方法已經被調用)。舉例來說,這可能發生在,如果一個前台活動在一個對話框(其他進程的)運行之後仍然是可視的,比如輸入法的彈出時。
  2. 寄宿著一個服務,該服務綁定到一個可視的活動。
  • 一個可視進程被認為是及其重要的且不會被殺死,除非為了保持前台進程運行。

5.3 服務進程

服務進程

  • 服務進程是通過 startService() 方法啟動的進程,但不屬於前台進程和可見進程。例如,在後台播放音樂或者在後台下載就是服務進程。

  • 系統保持它們運行,除非沒有足夠記憶體來保證所有的前台進程和可視進程。

5.4 後台進程

後台進程

  • 後台進程是一個保持著一個當前對用戶不可視的活動(已經調用 Activity 對象的 onStop() 方法)(如果還有除了 UI 執行緒外其他執行緒在運行話,不受影響)。

例如我正在使用 qq 和別人聊天,這個時候 qq 是前台進程,但是當我點擊 Home 鍵讓 qq 介面消失的時候,這個時候它就轉換成了後台進程。

  • 這些進程沒有直接影響用戶體驗,並且可以在任何時候被殺以收回記憶體用於一個前台、可視、服務進程。
  • 一般地有很多後台進程運行著,因此它們保持在一個 LRUleast recently used ,即最近最少使用,如果您學過作業系統的話會覺得它很熟悉,跟記憶體的頁面置換演算法 LRU 一樣)列表以確保最近使用最多的活動的進程最後被殺。

5.5 空進程

空進程

  • 空進程是一個沒有保持活躍的應用程式組件的進程,不包含任何活躍組件。

  • 保持這個進程可用的唯一原因是作為一個 cache 以提高下次啟動組件的速度。系統進程殺死這些進程,以在進程 cache 和潛在的內核 cache 之間平衡整個系統資源。

  • android 進程的回收順序從先到後分別是:空進程,後台進程,服務進程,可見進程,前台進程。

5.6 什麼是 ANR,如何避免

什麼是 ANR,如何避免

5.6.1 什麼是ANR

什麼是ANR

  • ANR ,全稱為 Application Not Responding
  • Android 中,如果你的應用程式有一段時間沒有響應,系統會向用戶顯示一個對話框,這個對話框稱作應用程式無響應對話框。

5.6.2 用戶行為

用戶行為

  • 用戶可以選擇讓程式繼續運行,也可以讓程式停止運行。
  • 他們在使用你的應用程式時,並不希望每次都要處理這個對話框。
  • 因此,在程式里對響應性能的設計很重要,這樣,系統不會顯示 ANR 給用戶。

5.6.3 Android不同組件ANR超時時間不同

Android不同組件ANR超時時間不同

  • 不同的組件發生 ANR 的時間不一樣,主執行緒( ActivityService )是 5 秒,BroadCastReceiver10 秒。

5.6.4 解決方案

解決方案

  1. 將所有耗時操作,比如訪問網路,Socket 通訊,查詢大量 SQL 語句,複雜邏輯計算等都放在子執行緒中去,然後通過 handler.sendMessagerunonUITreadAsyncTask 等方式更新 UI ,以確保用戶介面操作的流暢度。
  2. 如果耗時操作需要讓用戶等待,那麼可以在介面上顯示進度條。

5.7 android的任務棧 Task

android的任務棧 Task

  • 一個 Task 包含的就是 activity 集合,android 系統可以通過任務棧有序的管理 activity
  • 一個app當中可能不止一個任務棧,在某些情況下,一個 activity 也可以獨享一個任務棧( singleInstance 模式啟動的 activity

# 總結

  1. 本文基本涵蓋了 Android Activity 的所有知識點。對於 App 啟動、AMS 希望大家能根據文中鏈接或者 Google 搜索的形式繼續展開學習。
  2. 重點:關於 Android 的四大組件,到現在為止我才總結完 Activity ,馬上我將繼續針對,ServiceBroadcastRecevier 等,以及事件分發、滑動衝突、新能優化等重要模組,進行全面總結,歡迎大家關注 _yuanhao 的 部落格園 ,方便及時接收更新

碼字不易,你的點贊是我總結的最大動力!


Android