内容简介:目前,AAC(Android Architecture Components简称) 已经是 Android Jetpack 的一部分。Lifecycle 是 AAC 其中的一个组件,Lifecycle 能够管理 Activity 和 Fragment 的生命周期。Lifecycle 可以构建感知生命周期的组件 —— 这些组件根据 Activity、Fragment 的当前生命周期状态自动调整其行为。并且,LiveData 与 ViewModel 的 lifecycle 也依赖于 Lifecycle。首先,
一. Lifecycle
目前,AAC(Android Architecture Components简称) 已经是 Android Jetpack 的一部分。Lifecycle 是 AAC 其中的一个组件,Lifecycle 能够管理 Activity 和 Fragment 的生命周期。
Lifecycle 可以构建感知生命周期的组件 —— 这些组件根据 Activity、Fragment 的当前生命周期状态自动调整其行为。并且,LiveData 与 ViewModel 的 lifecycle 也依赖于 Lifecycle。
二. 创建 LifecycleObserver 的实现类
首先,创建一个 LifecycleObserver 接口的实现类 LifecycleCoroutineListener,在 Activity/Fragment 某个生命周期事件上(默认为Lifecycle.Event.ON_DESTROY),协程会调用取消的方法。
open class LifecycleCoroutineListener(private val job: Job,
private val cancelEvent: Lifecycle.Event = Lifecycle.Event.ON_DESTROY) : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun pause() = handleEvent(Lifecycle.Event.ON_PAUSE)
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop() = handleEvent(Lifecycle.Event.ON_STOP)
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun destroy() = handleEvent(Lifecycle.Event.ON_DESTROY)
private fun handleEvent(e: Lifecycle.Event) {
if (e == cancelEvent && !job.isCancelled) {
job.cancel()
}
}
}
复制代码
三. 列举使用场景
3.1 使用协程并绑定生命周期
创建 GlobalScope 的扩展函数 asyncWithLifecycle,它使用 async 创建一个 deferred 对象,并使用 lifecycleOwner 的 lifecycle 去绑定 LifecycleCoroutineListener。
fun <T> GlobalScope.asyncWithLifecycle(lifecycleOwner: LifecycleOwner,
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T): Deferred<T> {
val deferred = GlobalScope.async(context, start) {
block()
}
lifecycleOwner.lifecycle.addObserver(LifecycleCoroutineListener(deferred))
return deferred
}
复制代码
可以采用如下的方式进行使用,如果需要显示toast的话,必须使用 Dispatchers.Main 这样才能在主线程显示 toast:
GlobalScope.asyncWithLifecycle(this,Dispatchers.Main) {
delay(1000)
Toast.makeText(mContext,"hi, this must use 'Dispatchers.Main'",Toast.LENGTH_SHORT).show()
}
复制代码
使用 Dispatchers.Main 时,需要在 build.gradle 中添加
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1' 复制代码
3.2 协程的block绑定生命周期
创建 GlobalScope 的扩展函数 bindWithLifecycle,它的协程 block 在调用时绑定生命周期。
fun <T> GlobalScope.bindWithLifecycle(lifecycleOwner: LifecycleOwner,
block: CoroutineScope.() -> Deferred<T>): Deferred<T> {
val deferred = block.invoke(this)
lifecycleOwner.lifecycle.addObserver(LifecycleCoroutineListener(deferred))
return deferred
}
复制代码
可以采用如下的方式进行使用:
GlobalScope.bindWithLifecycle(this) {
GlobalScope.async(Dispatchers.Main) {
val deferred1 = async(Dispatchers.Default) {
delay(1000)
1
}
val deferred2 = async(Dispatchers.Default) {
delay(1500)
2
}
val result = deferred1.await() + deferred2.await()
Toast.makeText(mContext,"the result is $result",Toast.LENGTH_SHORT).show()
}
}
复制代码
3.3 then
创建 Deferred 的扩展函数 then,它会创建一个协程并运行在 UI 线程上:
infix fun <T> Deferred<T>.then(block: (T) -> Unit): Job {
return GlobalScope.launch(context = Dispatchers.Main) {
block(this@then.await())
}
}
复制代码
由于它使用了 infix ,并结合 asyncWithLifecycle 一起使用:
GlobalScope.asyncWithLifecycle(this,Dispatchers.IO) {
delay(5000) // 模拟耗时的网络请求
1
} then {
Toast.makeText(mContext,"the result is $it",Toast.LENGTH_SHORT).show()
}
复制代码
asyncWithLifecycle 使用了 Dispatchers.IO 来模拟一些耗时的网络请求。在实际开发中也可以这样使用,网络请求的结果使用 then 进行展示。
3.4 thenAsync
thenAsync 类似于 then,区别在于返回的对象不同。
infix fun <T, R> Deferred<T>.thenAsync(block: (T) -> R): Deferred<R> {
return GlobalScope.async(context = Dispatchers.Main) {
block(this@thenAsync.await())
}
}
复制代码
thenAsync 返回的是 Deferred 对象,因此可以使用如下的链式调用:
GlobalScope.asyncWithLifecycle(this, Dispatchers.IO) {
delay(5000) // 模拟耗时的网络请求
1
} thenAsync {
it + 2
} then {
Toast.makeText(mContext,"the result is $it", Toast.LENGTH_SHORT).show()
}
复制代码
3.5 awaitOrNull
创建 Deferred 的扩展函数 awaitOrNull,它参考了 Java 的 Future 的超时方法。如果遇到超时或者异常,则返回null。
suspend fun <T> Deferred<T>.awaitOrNull(timeout: Long = 0L): T? {
return try {
if (timeout > 0) {
withTimeout(timeout) {
this@awaitOrNull.await()
}
} else {
this.await()
}
} catch (e: Exception) {
Log.e("Deferred", e.message)
null
}
}
复制代码
下面的例子中,deferred 会在 5秒才有返回值,但是deferred 使用了awaitOrNull(),它的超时时间是4秒,因此 result 的值为 null。
val deferred = GlobalScope.asyncWithLifecycle(this, Dispatchers.IO) {
delay(5000) // 模拟耗时的网络请求
1
}
GlobalScope.asyncWithLifecycle(this,Dispatchers.Main) {
val result = deferred.awaitOrNull(4000)
Toast.makeText(mContext,"the result is $result", Toast.LENGTH_SHORT).show()
}
复制代码
如果把超时时间设置大于5秒的话,result 会返回正确的值。
3.6 任意 job 绑定到生命周期
还记得最初的 LifecycleCoroutineListener 嘛?它使用了 open ,因此任意创建的协程都可以使用它来绑定生命周期。
以上所述就是小编给大家介绍的《AAC 的 Lifecycle 结合 Kotlin Coroutines 进行使用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- MXNet 结合 kubeflow 进行分布式训练
- 使用递归进行数组的每一项的组合(结合)
- Zeppelin0.7.2结合hive解释器进行报表展示
- soap注入某sql2008服务器结合msf进行提权
- Android Paging分页库的学习(一)—— 结合本地数据进行分页加载
- 如何使用 KittyFuzzer 结合 ISF 中的工控协议组件对工控协议进行 Fuzz
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ajax Design Patterns
Michael Mahemoff / O'Reilly Media / 2006-06-29 / USD 44.99
Ajax, or Asynchronous JavaScript and XML, exploded onto the scene in the spring of 2005 and remains the hottest story among web developers. With its rich combination of technologies, Ajax provides a s......一起来看看 《Ajax Design Patterns》 这本书的介绍吧!