文章目錄
一、導入 Library
在 build.gradle 中導入庫:
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0'
添加 Java 和 Kotlin 的 java8 支持:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
二、監聽 Activity 生命週期
監聽生命週期有兩種方式,一是繼承 DefaultLifecycleObserver,在其重載方法中處理。二是使用註解,在方法上添加生命週期回調事件的註解,就能接收到對應回調。
Google 官方推薦使用方式一,因爲隨着 Java8 的流行,註解可能會被廢棄。
方式一:繼承 DefaultLifecycleObserver
新建 MyLifecycleObserver 類,繼承自 DefaultLifecycleObserver
class MyLifecycleObserver : DefaultLifecycleObserver{
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
Log.d("~~~", "onCreate")
}
override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
Log.d("~~~", "onResume")
}
override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
Log.d("~~~", "onPause")
}
override fun onStart(owner: LifecycleOwner) {
super.onStart(owner)
Log.d("~~~", "onStart")
}
override fun onStop(owner: LifecycleOwner) {
super.onStop(owner)
Log.d("~~~", "onStop")
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
Log.d("~~~", "onDestroy")
}
}
在需要監聽生命週期的 Activity 中,給 lifecycle 添加此觀察者:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycle.addObserver(MyLifecycleObserver())
}
}
大功告成,現在這個 activity 的生命週期回調觸發時,MyLifecycleObserver 的對應方法就能監聽到了。
方式二:使用註解
新建 MyLifecycleObserver 類,讓其繼承自 LifecycleObserver。通過給方法添加 OnLifecycleEvent
註解的方式監聽生命週期。
class MyLifecycleObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun create() {
Log.d("~~~", "ON_CREATE")
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start() {
Log.d("~~~", "ON_START")
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun resume() {
Log.d("~~~", "ON_RESUME")
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun pause() {
Log.d("~~~", "ON_PAUSE")
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop() {
Log.d("~~~", "ON_STOP")
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun destroy() {
Log.d("~~~", "ON_DESTROY")
}
}
在需要監聽生命週期的 Activity 中,給 lifecycle 添加此觀察者:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycle.addObserver(MyLifecycleObserver())
}
}
兩種方式的效果是一樣的。
三、Lifecycle 的狀態
3.1.五種狀態
Lifecycle 一共有五種狀態,分別是:
- INITIALIZED
- CREATED
- STARTED
- RESUMED
- DESTROYED
官網上用一張圖表示了 Lifecycle 的狀態與生命週期的關係:
3.2.狀態改變的時機
我們修改一下 MainActivity,來測一下 Lifecycle 的幾種狀態改變的時機。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Log.d("~~~", "OnCreate start, ${lifecycle.currentState}")
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycle.addObserver(MyLifecycleObserver())
Log.d("~~~", "OnCreate end, ${lifecycle.currentState}")
}
override fun onStart() {
Log.d("~~~", "onStart start, ${lifecycle.currentState}")
super.onStart()
Log.d("~~~", "onStart end, ${lifecycle.currentState}")
}
override fun onResume() {
Log.d("~~~", "onResume start, ${lifecycle.currentState}")
super.onResume()
Log.d("~~~", "onResume end, ${lifecycle.currentState}")
Thread(Runnable {
Thread.sleep(1000)
Log.d("~~~", "waiting 1 second after onResume, ${lifecycle.currentState}")
}).start()
}
override fun onPause() {
Log.d("~~~", "onPause start, ${lifecycle.currentState}")
super.onPause()
Log.d("~~~", "onPause end, ${lifecycle.currentState}")
}
override fun onStop() {
Log.d("~~~", "onStop start, ${lifecycle.currentState}")
super.onStop()
Log.d("~~~", "onStop end, ${lifecycle.currentState}")
}
override fun onDestroy() {
Log.d("~~~", "onDestroy start, ${lifecycle.currentState}")
super.onDestroy()
Log.d("~~~", "onDestroy end, ${lifecycle.currentState}")
}
}
運行程序,程序打開後,等待 1 秒多的時間(等待 1 秒是爲了便於觀察 RESUMED 狀態),點擊返回鍵退出。Log 輸出如下:
2020-03-03 22:29:39.569 20742-20742/com.example.myapplication D/~~~: OnCreate start, currentState is INITIALIZED
2020-03-03 22:29:39.747 20742-20742/com.example.myapplication D/~~~: OnCreate end, currentState is INITIALIZED
2020-03-03 22:29:39.750 20742-20742/com.example.myapplication D/~~~: ON_CREATE
2020-03-03 22:29:39.754 20742-20742/com.example.myapplication D/~~~: onStart start, currentState is CREATED
2020-03-03 22:29:39.758 20742-20742/com.example.myapplication D/~~~: onStart end, currentState is CREATED
2020-03-03 22:29:39.758 20742-20742/com.example.myapplication D/~~~: ON_START
2020-03-03 22:29:39.759 20742-20742/com.example.myapplication D/~~~: onResume start, currentState is STARTED
2020-03-03 22:29:39.759 20742-20742/com.example.myapplication D/~~~: onResume end, currentState is STARTED
2020-03-03 22:29:39.760 20742-20742/com.example.myapplication D/~~~: ON_RESUME
2020-03-03 22:29:40.761 20742-20794/com.example.myapplication D/~~~: waiting 1 second after onResume, currentState is RESUMED
2020-03-03 22:29:48.028 20742-20742/com.example.myapplication D/~~~: ON_PAUSE
2020-03-03 22:29:48.028 20742-20742/com.example.myapplication D/~~~: onPause start, currentState is STARTED
2020-03-03 22:29:48.029 20742-20742/com.example.myapplication D/~~~: onPause end, currentState is STARTED
2020-03-03 22:29:48.655 20742-20742/com.example.myapplication D/~~~: ON_STOP
2020-03-03 22:29:48.655 20742-20742/com.example.myapplication D/~~~: onStop start, currentState is CREATED
2020-03-03 22:29:48.656 20742-20742/com.example.myapplication D/~~~: onStop end, currentState is CREATED
2020-03-03 22:29:48.660 20742-20742/com.example.myapplication D/~~~: ON_DESTROY
2020-03-03 22:29:48.660 20742-20742/com.example.myapplication D/~~~: onDestroy start, currentState is DESTROYED
2020-03-03 22:29:48.661 20742-20742/com.example.myapplication D/~~~: onDestroy end, currentState is DESTROYED
經過測試,我們發現打開 app 時:
- Lifecycle 在 Activity 的 onCreate 方法中,狀態一直是 INITIALIZED。Activity 的 onCreate 執行完後,纔會回調 Observer 的 onCreate 方法,然後狀態變成 CREATED
- Lifecycle 在 Activity 的 onStart 方法中,狀態一直是 CREATED。Activity 的 onStart 執行完後,纔會回調 Observer 的 onStart 方法,然後狀態變成 STARTED
- Lifecycle 在 Activity 的 onResume 方法中,狀態一直是 STARTED。Activity 的 onResume 執行完後,纔會回調 Observer 的 onResume 方法,然後狀態變成 RESUMED
關閉 app 時:
- Activity 的 onPause 執行前,先回調 Lifecycle 的 onPause 方法,Lifecycle 狀態變爲 STARTED。然後再去執行 Activity 的 onPause 方法,在 Activity 的 onPause 方法中,Lifecycle 的狀態一直是 STARTED
- Activity 的 onStop 執行前,先回調 Lifecycle 的 onStop 方法,Lifecycle 狀態變爲 CREATED。然後再去執行 Activity 的 onStop 方法,在 Activity 的 onStop 方法中,Lifecycle 的狀態一直是 CREATED
- Activity 的 onDestroy 執行前,先回調 Lifecycle 的 onDestroy 方法,Lifecycle 狀態變爲 DESTROYED。然後再去執行 Activity 的 onDestroy 方法,在 Activity 的 onDestroy 方法中,Lifecycle 的狀態一直是 DESTROYED
總結起來就是:進入時最後改 Lifecycle 狀態,退出時最先改 Lifecycle 狀態。
3.3.active 與 inactive 的 Lifecycle
當 Lifecycle 處於 STARTED 或 RESUMED 狀態時,我們認爲 Lifecycle 是 active 的,否則認爲是 inactive 的。
四、監聽 Application 生命週期
監聽整個 app 的生命週期,官方文檔推薦使用 ProcessLifecycleOwner。
同樣可以使用繼承或註解兩種方式。MyLifecycleObserver 類和上述代碼一模一樣。在 Application 中,使用 ProcessLifecycleOwner 添加此觀察者:
class MyApplication : Application(), LifecycleObserver {
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(MyLifecycleObserver())
}
}
當 app 啓動時,依次回調 onCreate、onStart、onResume,當 app 退出時,依次回調 onPause、onStop,並且永遠不會回調 onDestroy。官方文檔中提到,onPause、onStop 回調是有一定間隔的,目的是保證在手機旋轉等配置改變時引起的 Activity 銷燬和重建時不發送 Event。查看源碼可以發現,這個間隔時間是 700ms。並且源碼中是通過監聽前臺 Activity 的數量實現的此功能。我們也可以通過這種方式來監聽 app 前後臺切換。
注:筆者在 mac 的安卓模擬器上使用 ProcessLifecycleOwner 沒有監聽到 onPause、onStop 回調,但 Windows 的模擬器上可以監聽到,暫不清楚原因。
五、監聽 app 前後臺切換
新建 MyActivityLifecycleCallbacks 單例:
object MyActivityLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
private var foregroundActivityCounts = 0
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
}
override fun onActivityStarted(activity: Activity) {
if (foregroundActivityCounts++ == 0) {
Log.d("~~~", "foreground")
}
}
override fun onActivityResumed(activity: Activity) {
}
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityStopped(activity: Activity) {
if (--foregroundActivityCounts == 0) {
Log.d("~~~", "background")
}
}
override fun onActivityDestroyed(activity: Activity) {
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
}
fun isAppForeground(): Boolean {
return foregroundActivityCounts > 0
}
}
在 Application 中註冊此 LifecycleCallbacks
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
registerActivityLifecycleCallbacks(MyActivityLifecycleCallbacks)
}
}
在 MyActivityLifecycleCallbacks 中,我們維護了一個 int 變量 foregroundActivityCounts ,用來記錄此 app 前臺 Activity 的數量。
每當 Activity 的 onStart
回調時,foregroundActivityCounts++,每當 Activity 的 onStop
回調時,–foregroundActivityCounts。
如果 foregroundActivityCounts 從 0 變成 1,說明 app 進入前臺,如果 foregroundActivityCounts 從 1 變成 0,說明 app 進入後臺。
MyActivityLifecycleCallbacks 聲明瞭 isAppForeground
方法,通過 foregroundActivityCounts 是否大於 0 來判斷 app 是否在前臺。
六、總結
在應用開發中,我們常常會有一些邏輯需要與生命週期綁定。比如:頁面展示在前臺時播放視頻,切換到後臺時暫停播放。應用開始時初始化,應用退出時釋放資源。通過本文介紹的這些監聽方法,可以讓這些代碼邏輯自己處理生命週期,實現更好的解耦。
僞代碼表示如下,使用 Lifecycle 前:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
LibraryA.init()
LibraryB.init()
LibraryC.init()
}
override fun onResume() {
super.onResume()
LibraryA.resume()
LibraryB.resume()
LibraryC.resume()
}
override fun onPause() {
super.onPause()
LibraryA.pause()
LibraryB.pause()
LibraryC.pause()
}
override fun onDestroy() {
super.onDestroy()
LibraryA.release()
LibraryB.release()
LibraryC.release()
}
}
使用 Lifecycle 後:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycle.addObserver(LifecycleObserverA())
lifecycle.addObserver(LifecycleObserverB())
lifecycle.addObserver(LifecycleObserverC())
}
}