什么是kotlin
这个都不知道的话,请打开官网😂
什么是coroutine
说起‘协程’可能有些人会比较熟悉,类似Lua、C#里面的概念。
Coroutines中文名”协程”,简单来说就是使用suspend来代替线程阻塞,可以理解为无阻塞的异步编写方式,基本原理是使用更轻的协程来代替繁重的阻塞操作,并且复用原本阻塞的线程资源。
本文仅简单介绍协程,如果你想知道更多关于协程,请参考这篇文章
Android生命周期
Android有一套基于用户行为的生命周期管理,用于及时释放资源。
问题
Android异步执行耗时任务,然后在主线程回调结果,如果在activity onDestroy之前没有取消掉,那么就会执行已经释放掉的UI资源,导致crash。
官方方案局限
Coroutines虽然返回了Job用于控制协程的取消,对Job的控制粒度非常细,但是每个任务都需要单独写控制代码,代码比较冗余。
另外官方还提供了另一种解决办法,这种办法可以减少一点冗余的代码,但是并没有达到简洁优雅的目的。
自己扩展
官方的不行,就自己来。其实,我们需要的是一个类似AutoDispose的扩展方法,只需要声明是需要生命周期管理的,就自动帮我们取消UI任务。
目的明确了,我们实现起来就简单很多。
1、作用范围
Android里面具有生命周期的UI组件只有Activity、Fragment和View,扩展方法只需要实现这三个作用域就可以了,而Activity和Fragment都实现了LifecycleOwner接口,我们只需要对LifecycleOwner扩展即可。
2、实现方式
LifecycleOwner只需要在发ON_DESTROY的时候,取消任务即可
class CoroutineLifecycleListener(private val deferred: Deferred<*>) : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun cancelCoroutine() {
if (!deferred.isCancelled) {
deferred.cancel()
}
}
}
同理,View在onViewDetachedFromWindow取消任务
class CoroutineViewListener(private val deferred: Deferred<*>) : View.OnAttachStateChangeListener {
override fun onViewDetachedFromWindow(v: View?) {
if (!deferred.isCancelled) {
deferred.cancel()
}
}
override fun onViewAttachedToWindow(v: View?) {
}
}
在回调主线程的时候,我们需要提供一个block用于UI操作,另外我们利用kotlin的infix关键字,使用起来更像DSL
infix fun <T> Deferred<T>.then(block: (T) -> Unit): Job {
return launch(UI) { block(this@then.await()) }
}
infix fun <T, R> Deferred<T>.then(block: (T) -> R): Deferred<R> {
return async(UI) { block(this@then.await()) }
}
3、结果
最终我们达到了我们的目的----简单优雅
load {
IOJob()
} then {
UIJob()
}
广告时间
写了这么多,当然是需要提供下这个库的地址😂
使用
根目录下的build.gradle添加
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
然后添加依赖
implementation 'com.github.TinoGuo:LifecycleKt:v1.0'
之后就可以愉快的使用了!
欢迎大家star或pr