Jetpack练手(04):Lifecycle

tech2022-12-10  65

文章目录

一、搭建布局二、非 Lifecycle 实现三、Lifecycle 实现四、Demo 效果


一、搭建布局

新建 LifecycleDemo 工程实现 界面停留时间计时,在 activity_main.xml 搭建简单布局(省略属性),如下:

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout tools:context=".MainActivity"> <Chronometer android:id="@+id/chronometer" /> </androidx.constraintlayout.widget.ConstraintLayout>

仅有一个控件:

chronometer - Chronometer,计时器。

整体布局如下:


二、非 Lifecycle 实现

在 MainActivity 类中,重写 onResume() 和 onPause() 如下:

class MainActivity : AppCompatActivity() { private var elapsedTime: Long = 0L override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } override fun onResume() { super.onResume() // 更新计时器 base 时间 chronometer.base = SystemClock.elapsedRealtime() - elapsedTime chronometer.start() } override fun onPause() { super.onPause() // 记录 Activity onPause 时已经经过时间 elapsedTime = SystemClock.elapsedRealtime() - chronometer.base chronometer.stop() } }

可以举一个直观的例子理解一下:

系统启动000102030405060708091011121314SystemClock.elapsedRealtime()000102030405060708091011121314① Activity onResume▶① chronometer.base03② elapsedTime01234② Activity onPause!! 在系统启动 3s 后启动 Activity,此时设置 Chronometer 的 base 为当前系统启动后经过的时间,即 3s;Activity 前台运行 4s 后退到后台,此时经过的时间 elapsedTime = SystemClock.elapsedRealtime() - chronometer.base,即 7 - 3 = 4s。 系统启动000102030405060708091011121314SystemClock.elapsedRealtime()000102030405060708091011121314① Activity onResume▶② elapsedTime01234② chronometer.base03→05 Activity 退到后台之后又经过 2s,SystemClock.elapsedRealtime() 走到了 9s,此时将 Activity 拉起到前台;要保证计时器数字不变,需要调整它的 base 与当前系统经过时间的差值不变,即调整 base 为 5s,chronometer.base = SystemClock.elapsedRealtime() - elapsedTime,即 9 - 4 = 5s。 系统启动000102030405060708091011121314SystemClock.elapsedRealtime()000102030405060708091011121314① chronometer.base05① elapsedTime0123456789 此时 Activity 在前台,Chronometer 可以按照调整后的 base 正常计时。

效果如下:


三、Lifecycle 实现

上面示例看起来没什么问题,但在真实的应用中,会有很多界面管理和组件调用,在 onXXXX() 生命周期回调中放置大量的代码,会变得难以维护。因此需要以弹性和隔离的方式解决这些问题,Lifecycle 组件提供了这样的方式,所以可以尝试使用 Lifecycle 重新实现上面示例。

首先,自定义一个计时器控件 MyChronometer 继承自 Chronometer 并实现 LifecycleObserver 接口:

class MyChronometer @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : Chronometer(context, attrs, defStyleAttr), LifecycleObserver {}

通过向 MyChronometer 类中的方法添加注解来监控组件的生命周期状态,方法内具体逻辑和上面类似:

class MyChronometer @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : Chronometer(context, attrs, defStyleAttr), LifecycleObserver { private var elapsedTime: Long = 0L @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) private fun resumeChronometer() { base = SystemClock.elapsedRealtime() - elapsedTime start() } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) private fun pauseChronometer() { elapsedTime = SystemClock.elapsedRealtime() - base stop() } }

修改 activity_main.xml 中使用自定义计时器控件 MyChronometer:

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout tools:context=".MainActivity"> <com.example.lifecycledemo.MyChronometer android:id="@+id/chronometer" /> </androidx.constraintlayout.widget.ConstraintLayout>

在 MainActivity 中通过调用 Lifecycle 类的 addObserver() 方法并传递观察者的实例来添加观察者:

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) lifecycle.addObserver(chronometer) } }

四、Demo 效果

效果如下:


最新回复(0)