1. 坑人的 Handler
大家都知道 Handler 特别坑,使用不当会造成各种问题:
Activity中使用 Handler 有可能会造成Context内存泄漏;Handler()默认构造函数会因为缺少Looper而崩溃(虽然已标位 deprecated ) ;View.post/postDelayed基于 Handler 实现,在View已经 detached 时可能仍在执行,造成异常
诸如上述这些问题让开发者们防不胜防,但是 Handler 便利性又让开发者们难以割舍。大家希望寻找一种同样方便但更安全的替代方案。如今借助 Kotlin Coroutine + Lifecycle 我们可以做到这一切,思路很简单:利用协程执行异步任务,同时绑定 Lifecycle ,在必要的时候终止任务
2. 替代 Handler.post/postDelayed
项目中添加 coroutie 和 lifecycle 依赖:
implementation "andoridx.lifecycle:lifecycle-runtime-ktx:2.3.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3"
代码如下
fun LifecycleOwner.postDelayedOnLifecycle(
duration: Long,
dispatcher: CoroutineDispatcher = Dispatchers.Main,
block: () -> Unit
): Job = lifecycleScope.launch(dispatcher) {
delay(duration)
block()
}
因为 Handler.post 运行在 UI 线程, 所以 Dispatcher 默认使用 Dispatchers.Main,postDelayed 的延时使用 delay 实现。
使用效果如下,在 Activity 或 Fragment 中无需再依赖 Handler 了
class MainActivity : AppCompatActivity() {
...
postDelayedOnLifecycle(500L) {
//Do something
}
...
}
3. 替代 View.post/postDelayed
我们还可以借助 lifecycle-ktx 提供的 View 的扩展方法 findViewTreeLifecycleOwner(),替代 View.post / View.postDelayed , findViewTreeLifecycleOwner 可以从当前 View 最近的 Fragment 或者 Activity 获取 LifecycleOwner。
代码如下:
fun View.postDelayedOnLifecycle(
duration: Long,
dispatcher: CoroutineDispatcher = Dispatchers.Main,
block:() -> Unit
) : Job? = findViewTreeLifecycleOwner()?.let { lifecycleOwner ->
lifecycleOwner.lifecycleScope.launch(dispatcher) {
delay(duration)
block()
}
}