官术网_书友最值得收藏!

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所示。

022-1

圖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所示。

026-1

圖2-4 State返回值與Activity生命周期的對應關系

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

主站蜘蛛池模板: 海宁市| 德格县| 邵东县| 土默特右旗| 邛崃市| 镶黄旗| 灵璧县| 广东省| 台山市| 宜章县| 江陵县| 南平市| 金溪县| 内乡县| 岳阳县| 黑龙江省| 韶山市| 资兴市| 邵东县| 沂南县| 陇南市| 阿坝县| 迁西县| 贵阳市| 桑日县| 福泉市| 永清县| 南昌市| 静海县| 米易县| 海门市| 托克托县| 宜君县| 马尔康县| 明光市| 苍溪县| 灵丘县| 绥阳县| 阿拉善盟| 滦南县| 宁都县|