加入收藏 | 设为首页 | 会员中心 | 我要投稿 辽源站长网 (https://www.0437zz.com/)- 云专线、云连接、智能数据、边缘计算、数据安全!
当前位置: 首页 > 站长资讯 > 评论 > 正文

如何正确的在 Android 上使用 Kotlin 协程?

发布时间:2019-10-25 10:41:12 所属栏目:评论 来源:kengsirLi
导读:前言 你还记得是哪一年的 Google IO 正式宣布 Kotlin 成为 Android 一级开发语言吗?是 Google IO 2017 。如今两年时间过去了,站在一名 Android 开发者的角度来看,Kotlin 的生态环境越来越好了,相关的开源项目和学习资料也日渐丰富,身边愿意去使用或者

最后别忘了在 onDestroy() 中取消协程,通过扩展函数 cancel() 来实现:

  1. override fun onDestroy() { 
  2.  super.onDestroy() 
  3.  cancel() 

现在来测试一下 launchFromMainScope() 方法吧!你会发现这完全符合你的需求。实际开发中可以把 MainScope 整合到 BaseActivity 中,就不需要重复书写模板代码了。

ViewModelScope

如果你使用了 MVVM 架构,根本就不会在 Activity 上书写任何逻辑代码,更别说启动协程了。这个时候大部分工作就要交给 ViewModel 了。那么如何在 ViewModel 中定义协程作用域呢?还记得上面 MainScope() 的定义吗?没错,搬过来直接使用就可以了。

  1. class ViewModelOne : ViewModel() { 
  2.  private val viewModelJob = SupervisorJob() 
  3.  private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob) 
  4.  val mMessage: MutableLiveData<String> = MutableLiveData() 
  5.  fun getMessage(message: String) { 
  6.  uiScope.launch { 
  7.  val deferred = async(Dispatchers.IO) { 
  8.  delay(2000) 
  9.  "post $message" 
  10.  } 
  11.  mMessage.value = deferred.await() 
  12.  } 
  13.  } 
  14.  override fun onCleared() { 
  15.  super.onCleared() 
  16.  viewModelJob.cancel() 
  17.  } 

这里的 uiScope 其实就等同于 MainScope。调用 getMessage() 方法和之前的 launchFromMainScope() 效果也是一样的,记得在 ViewModel 的 onCleared() 回调里取消协程。

你可以定义一个 BaseViewModel 来处理这些逻辑,避免重复书写模板代码。然而 Kotlin 就是要让你做同样的事,写更少的代码,于是 viewmodel-ktx 来了。看到 ktx ,你就应该明白它是来简化你的代码的。引入如下依赖:

  1. implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-alpha03" 

然后,什么都不需要做,直接使用协程作用域 viewModelScope 就可以了。viewModelScope 是 ViewModel 的一个扩展属性,定义如下:

  1. val ViewModel.viewModelScope: CoroutineScope 
  2.  get() { 
  3.  val scope: CoroutineScope? = this.getTag(JOB_KEY) 
  4.  if (scope != null) { 
  5.  return scope 
  6.  } 
  7.  return setTagIfAbsent(JOB_KEY, 
  8.  CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main)) 
  9.  } 

看下代码你就应该明白了,还是熟悉的那一套。当 ViewModel.onCleared() 被调用的时候,viewModelScope 会自动取消作用域内的所有协程。使用示例如下:

  1. fun getMessageByViewModel() { 
  2.  viewModelScope.launch { 
  3.  val deferred = async(Dispatchers.IO) { getMessage("ViewModel Ktx") } 
  4.  mMessage.value = deferred.await() 
  5.  } 

写到这里,viewModelScope 是能满足需求的最简写法了。实际上,写完全篇,viewModelScope 仍然是我认为的最好的选择。

LiveData

Kotlin 同样为 LiveData 赋予了直接使用协程的能力。添加如下依赖:

  1. implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-alpha03" 

直接在 liveData {} 代码块中调用需要异步执行的挂起函数,并调用 emit() 函数发送处理结果。示例代码如下所示:

  1. val mResult: LiveData<String> = liveData { 
  2.  val string = getMessage("LiveData Ktx") 
  3.  emit(string) 

你可能会好奇这里好像并没有任何的显示调用,那么,liveData 代码块是在什么执行的呢?当 LiveData 进入 active 状态时,liveData{ } 会自动执行。当 LiveData 进入 inactive 状态时,经过一个可配置的 timeout 之后会自动取消。如果它在完成之前就取消了,当 LiveData 再次 active 的时候会重新运行。如果上一次运行成功结束了,就不会再重新运行。也就是说只有自动取消的 liveData{ } 可以重新运行。其他原因(比如 CancelationException)导致的取消也不会重新运行。

(编辑:辽源站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读