- Android Jetpack開發:原理解析與應用實戰
- 黃林晴
- 1496字
- 2022-07-05 09:43:56
2.2 Lifecycle的基本使用
2.2.1 使用Lifecycle優化廣告引導頁的需求
什么是Lifecycle呢?Lifecycle是Jetpack架構組件中用來感知生命周期的組件,使用Lifecycle可以幫助開發者寫出與生命周期相關且更簡潔、更易維護的代碼。這單純從定義上可能并不好理解,接下來通過優化上面所述廣告引導頁的功能來展示Lifecycle的具體使用方法。
首先在項目中添加Lifecycle組件的依賴項,代碼如下:
dependencies { ... def lifecycle_version = "2.2.0" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" ... }
接著在廣告管理類AdvertisingManage中實現LifecycleObserver接口,代碼如下:
object AdvertisingManage:LifecycleObserver { ... }
通過LifecycleObserver的源碼可以看出,LifecycleObserver是一個空接口,所以開發者不需要實現額外的方法。
然后通過OnLifecycleEvent注解將方法與生命周期綁定,比如,要在Activity onCreate的生命周期中執行AdvertisingManage類的onStart方法,且在onDestroy的生命周期中執行onCancel方法,那么可以采用如下代碼:
/** * 開始計時 */ @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun start() { Log.d(TAG, "開始計時") countDownTimer?.start() } /** * 停止計時 */ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun onCancel() { Log.d(TAG, "停止計時") countDownTimer?.cancel() countDownTimer = null }
當然僅這樣還不行,還要在Activity中通過addObserver方法注冊Advertising-Manage,此時應該將之前在Activity生命周期中主動調用的方法移除。修改后Activity的代碼如下:
class AdvertisingActivity : AppCompatActivity() { //跳過廣告按鈕 lateinit var btnIngore: Button //廣告時間 lateinit var tvAdvertisingTime: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_advertising) val advertisingManage = AdvertisingManage() lifecycle.addObserver(advertisingManage) btnIngore = findViewById(R.id.btn_ignore) tvAdvertisingTime = findViewById(R.id.tv_advertising_time) advertisingManage.advertisingManageListener = object : AdvertisingManage.AdvertisingManageListener { override fun timing(second: Int) { tvAdvertisingTime.text = "廣告剩余$second秒" } override fun enterMainActivity() { MainActivity.actionStart(this@AdvertisingActivity) finish() } } //跳過廣告點擊事件 btnIngore.setOnClickListener { MainActivity.actionStart(this@AdvertisingActivity) finish() } }
再次運行程序,打印日志如圖2-3所示。

圖2-3 打印日志
從圖2-3中可以看到,最終結果與之前的結果無異,但是使用Lifecycle改造后的實現方式極大簡化了Activity中的代碼邏輯,這種方式也使得業務功能與Activity業務邏輯分離。
現在回過頭來看OnLifecycleEvent的注解方法,其中,Lifecycle.Event的枚舉如下:
public enum Event { /** * Constant for onCreate event of the {@link LifecycleOwner}. */ ON_CREATE, /** * Constant for onStart event of the {@link LifecycleOwner}. */ ON_START, /** * Constant for onResume event of the {@link LifecycleOwner}. */ ON_RESUME, /** * Constant for onPause event of the {@link LifecycleOwner}. */ ON_PAUSE, /** * Constant for onStop event of the {@link LifecycleOwner}. */ ON_STOP, /** * Constant for onDestroy event of the {@link LifecycleOwner}. */ ON_DESTROY, /** * An {@link Event Event} constant that can be used to match all events. */ ON_ANY; }
上述代碼中,前面幾個狀態分別對應Activity的生命周期,最后一個ON_ANY狀態則表示可對應Activity的任意生命周期。
再來看注冊的方法lifecycle.addObserver(AdvertisingManage),為什么它可以直接調用getLifecycle方法呢?那是因為getLifecycle是接口LifecycleOwner的實現方法。LifecycleOwner的源碼如下:
public interface LifecycleOwner { /** * Returns the Lifecycle of the provider. * * @return The lifecycle of the provider. */ @NonNull Lifecycle getLifecycle(); }
通過追溯源碼可以發現,當前Activity繼承的是androidx.core.app.Component-Activity,而ComponentActivity實現了LifecycleOwner接口,所以開發者可以直接調用getLifecycle方法。實現ComponentActivity類的源碼如下:
public class ComponentActivity extends Activity implements LifecycleOwner, KeyEventDispatcher.Component { ... }
除了ComponentActivity之外,在ComponentActivity的子類androidx.fragment.app.FragmentActivity、androidx.appcompat.app.AppCompatActivity以及androidx.fragment.app.Fragment中都是可以直接使用Lifecycle的,這是AndroidX幫助開發者完成的。
如果當前Activity繼承的是沒有實現LifecycleOwner接口的android.app.Activity,會發生什么呢?為了便于測試,這里直接將當前Activity的繼承修改為android.app.Activity,之后你會看到lifecycle.addObserver(AdvertisingManage)這行代碼報錯了,這就是因為android.app.Activity沒有實現getLifecycle方法,這時,自定義LifecycleOwner就派上用場了。
2.2.2 自定義LifecycleOwner
使用getLifecycle方法的前提是當前父類實現了LifecycleOwner接口,因此若需要在沒有實現LifecycleOwner接口的類中使用該方法,則需要自定義LifecycleOwner。
首先,讓繼承自Activity類的頁面實現LifecycleOwner接口并重寫getLifecycle方法,修改后的代碼如下:
class AdvertisingActivity : Activity(), LifecycleOwner { //跳過廣告按鈕 lateinit var btnIngore: Button //廣告時間 lateinit var tvAdvertisingTime: TextView lateinit var lifecycleRegistry: LifecycleRegistry override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_advertising) val advertisingManage = AdvertisingManage() lifecycle.addObserver(advertisingManage) btnIngore = findViewById(R.id.btn_ignore) tvAdvertisingTime = findViewById(R.id.tv_advertising_time) advertisingManage.advertisingManageListener = object : AdvertisingManage.AdvertisingManageListener { override fun timing(second: Int) { tvAdvertisingTime.text = "廣告剩余$second秒" } override fun enterMainActivity() { MainActivity.actionStart(this@AdvertisingActivity) finish() } } //跳過廣告點擊事件 btnIngore.setOnClickListener { MainActivity.actionStart(this@AdvertisingActivity) finish() } } override fun getLifecycle(): Lifecycle { return lifecycleRegistry } }
如此,就實現了與繼承AppCompatActivity時同樣的效果。這樣一來就可以通過注解方法主動執行對應生命周期的方法了。如果開發者想主動獲取當前Activity的生命周期狀態,又該如何做呢?
開發者可以使用Lifecycle的getCurrentState方法,從源碼可以看出,getCurrentState會返回如下種類的State:
public enum State { DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED; }
State種類狀態返回值與Activity生命周期的對應關系如圖2-4所示。

圖2-4 State返回值與Activity生命周期的對應關系
如果getCurrentState返回的值是STARTED,則說明當前Activity已經執行了onStart方法,但是還未執行onResume方法,其他返回值可以此類推。Lifecycle的使用場景有很多,比如,在下載文件的需求中,想要節省流量,那么可以在App處于后臺時停止下載,當App置于前臺時又能自動恢復下載。這個功能的具體實現就交給讀者去嘗試了。接下來看看在實際項目中Lifecycle還可以解決哪些常見的問題。