Android 開發藝術探索讀書筆記 1 -- Activity 的生命周期和啟動模式

本篇文章主要介紹以下幾個知識點:

  • Activity 的生命周期全面分析;
  • Activity 的啟動模式。
hello,夏天 (圖片來源于網絡)

1.1 Activity 的生命周期全面分析

典型情況下的生命周期,指在有用戶參與的情況下,Activity 所經過的生命周期的改變。

異常情況下的生命周期,指 Activity 被系統回收或由于設備的 Configuration 改變導致 Activity 被銷毀重建。

1.1.1 典型情況下的生命周期分析

Activity 生命周期的切換過程

(1)針對一個特定的 Activity,首次啟動,回調如下:onCreate ->onStart -> onResume

(2)當用戶打開新的 Activity 或切換到桌面時,回調如下:onPause -> onStop。(注:若新 Activity 采用了透明主題,則當前 Activity 不會回調 onStop

(3)當用戶再次回到原 Activity 時,回調如下:onRestart -> onStart -> onResume

(4)當用戶按 back 鍵回退時,回調如下:onPause -> onStop -> onDestroy

(5)當 Activity 被系統回收后再次打開,生命周期方法回調過程和(1)一樣。(注:只是生命周期方法一樣,不代表所有過程都一樣

(6)整個生命周期:onCreateonDestroy 是配對的(標識著 Activity 的創建和銷毀,只調用一次)。
??Activity 是否可見:onStartonStop 是配對的(可能被調用多次);
??Activity 是否在前臺:onResumeonPause 是配對的(可能被調用多次)。

問題 1:onStartonResumeonPauseonStop 從描述上看差不多,對我們來說有什么實質的不同呢?
??答:這兩配對的回調具有不同的意義,onStartonStop 是根據 Activity 是否可見來回調的,而 onResumeonPause 是根據 Activity 是否位于前臺來回調的,除此之外,在實際使用中無其他明顯區別。

問題2:假設當前Activity為A,若這時用戶打開一個新Activity B,那么B的 onResume 和 A 的 onPause 哪個先執行呢?
??答:當新啟動一個 Activity 時,舊 Activity 的 onPause 會先執行,然后才會啟動新的 Activity。(注:onPauseonStop 都不能執行耗時的操作,尤其是 onPause

1.1.2 異常情況下的生命周期分析

  • 情況 1:資源相關的系統配置發生改變導致 Activity 被殺死并重新創建

在默認情況下,若 Activity 不做特殊處理,當系統配置發生改變后,Activity 就會被銷毀并重新創建,其生命周期如圖:

異常情況下 Activity 的重建過程

當系統配置發生改變后,Activity 會被銷毀,其 onPauseonStoponDestroy 均會被調用,同時由于 Activity 是在異常情況下終止的,系統會調用 onSaveInstanceState 來保存當前Activity 的狀態。

方法 onSaveInstanceState 的調用時機是在 onStop 之前(和 onPause 無既定的時序關系),并且只會在 Activity 被異常終止的情況下回調

當 Activity 被重新創建后,系統會調用 onRestoreInstanceState,并把 Activity 銷毀時 onSaveInstanceState 方法保存的 Bundle 對象作為參數同時傳遞給 onRestoreInstanceStateonCreate 方法。

因此,可以通過 onRestoreInstanceStateonCreate 方法來判斷 Activity 是否被重建了,若被重建了,可取出之前保存的數據并恢復。(onRestoreInstanceState 在 onStart 之后調用

關于保存和恢復 View 層次結構,其工作流程為:首先 Activity 被意外終止時,Activity 會調用 onSaveInstanceState 去保存數據,然后 Activity 會委托 Window 去保存數據,接著 Window 再委托它上面的頂級容器去保存數據。

  • 情況 2:資源內存不足導致低優先級的 Activity 被殺死

Activity 按照優先級從高到低,可以分為如下三種:

(1)前臺 Activity——正在和用戶交互的 Activity,優先級最高。

(2)可見但非前臺 Activity —— 如 Activity 中彈出一個對話框,導致 Activity 可見但位于后臺無法和用戶直接交互。

(3)后臺 Activity——已經被暫停的 Activity,如執行了 onStop,優先級最低。

當系統內存不足時,系統會按上述優先級殺死目標 Activity 所在的進程,并在后續通過 onSaveInstanceStateonRestoreInstanceState 來存儲和恢復數數據。

系統配置中有很多內容,當某項內容改變后,若不想系統重新創建 Activity,可以給 Activity 指定 configChanges 屬性。

如給 configChanges 屬性添加 android:configChanges="orientation" 可避免 Activity 在屏幕旋轉時重新創建。

若想指定多個值,可用“|”連接起來,如 android:configChanges="orientation|keyboardHidden"

系統配置中所含的項目很多,如下:

configChanges 的項目和含義

上表中項目很多,但常用的只有 localeorientationkeyboardHidden 這三個。

值得注意的是 ,screenSizesmallestScreenSize 比較特殊,它們的行為和編譯選項有關,和運行環境無關。

1.2 Activity 的啟動模式

1.2.1 Activity 的 LaunchMode

(1)standard:標準模式。

系統的默認模式,每次啟動一個 Activity 都會重新創建一個新的實例,不管這個實例是否已存在。

值得注意的是,用 ApplicationContext 去啟動 standard 模式的 Activity 時會報錯,如以下代碼:

 tv_text.setOnClickListener {
     // 點擊跳轉到 KotlinActivity
     val intent = Intent()
     intent.setClass(applicationContext, KotlinActivity::class.java)
     applicationContext.startActivity(intent)
 }

運行會報如下錯誤:

standard 模式下用ApplicationContext 啟動 Activity 報錯

這是因為 standard 模式的 Activity 默認會進入啟動它的 Activity 所屬的任務棧中,但由于非 Activity 類型的 Context(如 ApplicationContext)并無所謂的任務棧,從而報錯。

解決上面問題的方法是為待啟動 Activity 指定 FLAG_ACTIVITY_NEW_TASK 標記位,這樣啟動時就會為它創建一個新的任務棧(此時待啟動 Activity 是以 singleTask 模式啟動的)。

(2)singleTop:棧頂復用模式。

此模式下,若新 Activity 已經位于任務棧的棧頂,則此 Activity 不會被重新創建,同時它的 onNewIntent 方法會被回調,通過此方法的參數可以取出當前請求的信息。

值得注意的是,這個 Activity 的 onCreateonStart 不會被系統調用,因為它并沒有發生改變。

(3)singleTask:棧內復用模式。

一種單實例模式,此模式下,只要 Activity 在一個棧中存在,那么多次啟動此 Activity 都不會重新創建實例,和 singleTop 一樣,系統也會回調其 onNewIntent

(4)singleInstance:單實例模式。

一種加強的 singleTask 模式,具有 singleTask 模式的所有特性,并且具有此種模式的 Activity 只能單獨地位于一個任務棧中。


給 Activity 指定啟動模式有兩種方法:

1. 通過 AndroidMenifest 為 Activity 指定啟動模式

2. 通過在 Intent 中設置標志位為 Activity 指定啟動模式。

二者區別在于:

(1) 優先級上,方式2的優先級高于方式1,當兩種同時存在時,以方式2為準;

(2) 限定范圍不同,比如,方式1無法直接為 Activity 設定 FLAG_ACTIVITY_CLEAR_TOP 標識,而方式2無法為 Activity 指定 singleInstance 模式。


1.2.2 Activity 的 Flags

Activity 的 Flags 有很多,有的標記位可以設定 Activity 的啟動模式,有的會影響 Activity 的運行狀態等。常用的如下:

  • FLAG_ACTIVITY_NEW_TASK

其作用是為 Activity 指定 singleTask 啟動模式,效果和在 XML 中指定該模式相同。

  • FLAG_ACTIVITY_SINGLE_TOP

其作用是為 Activity 指定 singleTop 啟動模式,效果和在 XML 中指定該模式相同。

  • FLAG_ACTIVITY_CLEAR_TOP

具有此標記位的 Activity 啟動時,在同一個任務棧中所有位于它上面的 Activity 都要出棧。

此模式一般需要和 FLAG_ACTIVITY_NEW_TASK 配合使用,若被啟動Activity 的實例已存在,則系統會調用它的 onNewIntent

  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具有此標記的 Activity 不會出現在歷史 Activity 的列表中(用于某些情況不希望用戶通過歷史列表回到 Activity 時)。它等同于在 XML 中指定 Activity 的屬性 android:excludeFromRecents="true"

本篇文章就介紹到這。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容