kotlin协程-Android实战

fun launchWhenStarted(block: suspend CoroutineScope.() -> Unit): Job = launch {
lifecycle.whenStarted(block)
}

// 当 activity 处于resume的时候执行 协程体
fun launchWhenResumed(block: suspend CoroutineScope.() -> Unit): Job = launch {
lifecycle.whenResumed(block)
}
}

由于上面启动协程的方法绑定了activity生命周期,所以在activity destroy的时候,也实现了自动cancel掉协程

所以我们 CoroutineActivity Demo的代码可以写的更加简单,如下:

class CoroutineActivity : AppCompatActivity() {
private lateinit var testApi: TestApi

fun requestData1() {
lifecycleScope.launchWhenResumed {
try {
val lastedNews = testApi.getLatestNews2()
tv_text.text = lastedNews.stories!![0].title
} catch(e: Exception) {
tv_text.text = “error”
}
}
}
}

LiveData对协程的支持

同时Google也对LiveData提供了对协程的支持,不过需要添加lifecycle-livedata-ktx依赖

// 现在还是alpha版,等正式版发布以后,请替换成正式版
implementation “androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-alpha05”

lifecycle-livedata-ktx依赖添加了liveData顶级函数,返回CoroutineLiveData

源码如下:


internal const val DEFAULT_TIMEOUT = 5000L

fun liveData(
context: CoroutineContext = EmptyCoroutineContext,
timeoutInMs: Long = DEFAULT_TIMEOUT,
@BuilderInference block: suspend LiveDataScope.() -> Unit
): LiveData = CoroutineLiveData(context, timeoutInMs, block)

CoroutineLiveData是在什么时候启动协程并执行协程体的呢???

internal class CoroutineLiveData(
context: CoroutineContext = EmptyCoroutineContext,
timeoutInMs: Long = DEFAULT_TIMEOUT,
block: Block
) : MediatorLiveData() {
private var blockRunner: BlockRunner?
private var emittedSource: EmittedSource? = null

init {
val scope = CoroutineScope(Dispatchers.Main.immediate + context + supervisorJob)
blockRunner = BlockRunner(
liveData = this,
block = block,
timeoutInMs = timeoutInMs,
scope = scope
) {
blockRunner = null
}
}

// observer(观察者)个数有0到1时执行
// 即第一次调用observe或observeForever时执行
override fun onActive() {
super.onActive()
// 启动协程并执行协程体
blockRunner?.maybeRun()
}

// observer(观察者)个数有1到0时执行
// 即调用removeObserver时触发检查并执行回调
override fun onInactive() {
super.onInactive()
// 取消协程
blockRunner?.cancel()
}
}

可见CoroutineLiveData是在onActive()启动协程,在onInactive()取消协程

所以使用LiveData对协程的支持, 那么CoroutineActivity Demo的代码写法如下

class CoroutineActivity : AppCompatActivity() {
private lateinit var testApi: TestApi

fun requestData1() {
liveData {
try {
val lastedNews = testApi.getLatestNews2()
emit(lastedNews.stories!![0].title!!)
} catch(e: Exception) {
emit(“error”)
}
}.observe(this, Observer {
tv_text.text = it
})
}
}

上面我们讲了协程在android里最常用的用法,下面将介绍协程的一些基本知识

协程上下文

协程上下文用CoroutineContext表示,kotlin中 比较常用的Job协程调度器(CoroutineDispatcher)协程拦截器(ContinuationInterceptor)等都是CoroutineContext的子类,即它们都是协程上下文

先看一下CoroutineContext 比较重要的plus方法,它是一个用operator修复的重载(+)号的操作符方法

@SinceKotlin(“1.3”)
public interface CoroutineContext {

/**

  • Returns a context containing elements from this context and elements from other [context].
  • The elements from this context with the same key as in the other one are dropped.
    */
    public operator fun plus(context: CoroutineContext): CoroutineContext =
    if (context === EmptyCoroutineContext) this else // fast path – avoid lambda creation
    context.fold(this) { acc, element ->
    val removed = acc.minusKey(element.key)
    if (removed === EmptyCoroutineContext) element else {
    // make sure interceptor is always last in the context (and thus is fast to get when present)
    val interceptor = removed[ContinuationInterceptor]
    if (interceptor == null) CombinedContext(removed, element) else {
    val left = removed.minusKey(ContinuationInterceptor)

你可能感兴趣的:(程序员,android,kotlin,开发语言)