Kotlin 协程之三:Android中的应用

  • 1.将线程改为协程
  • 2.将网络请求改为协程
  • 3.生命周期

系列文章:
Kotlin 协程之一:基础使用
Kotlin 协程之二:原理剖析
Kotlin 协程之三:Android中的应用

至此,我们完全了解了协程的使用和实现原理,那么如何应用到我们Android项目中呢?这里讲一些简单的例子。

1.将线程改为协程

通常我们有一些小的延时任务或异步任务,会使用线程池来解决,这里我们可以用协程来解决,比如:在页面创建后,异步读取数据库中的内容,然后展示到TextView上。

CoroutineScope(Dispatchers.Main).launch {  val data = withContext(Dispatchers.IO){ //get data from DB }  textView.text = data}

2.将网络请求改为协程

通常我们的网络请求都是使用的第三方库,如retrofit等,他们的共同点都是结果需要通过Callback回调,这显然是我们不愿意看到的,这里我们可以改为协程实现。

//假如这是网络库的Call对象private class Call(data: String = "") {  fun addCallback(cb: Callback) {    //register callback  }}private interface Callback {  fun onCall(res: String)  fun onError(error: Exception)}

假如这是网络库的Call对象,我们通过其来添加Callback,那么我们为他增加一个扩展函数。

private suspend fun Call.await(): String = suspendCancellableCoroutine {  addCallback(object : Callback {    //请求异常时调用resumeWithException恢复协程    override fun onError(error: Exception) {      it.resumeWithException(error)    }    //请求成功时调用resume恢复协程    override fun onCall(res: String) {      it.resume(res)    }  })}

这样一来,我们的请求和处理就可以写成协程的样子,甚至多个有依赖关系的接口也支持:

CoroutineScope(Dispatchers.Main).launch {  val data1 = Call().await()  val data2 = Call(data1).await()  textView.text = data2   }

这样一来,我们大量回调嵌套的异步任务就清晰了很多。

3.生命周期

以上都是我们如何使用协程完成一个任务,那么对于应用来说,还要考虑的是声明周期,就比如网络请求在页面退出时应该及时cancel,有效避免资源浪费、崩溃和内存泄露。

open class BaseActivity : AppCompatActivity() {    private val scope = CoroutineScope(Dispatchers.Main)        fun startCoroutine(context: CoroutineContext = EmptyCoroutineContext,                       start: CoroutineStart = CoroutineStart.DEFAULT,                       block: suspend CoroutineScope.() -> Unit): Job = scope.launch(context, start, block)    override fun onDestroy() {        super.onDestroy()        scope.cancel()    }}

首先我们可以在基类创建一个scope,每个页面一个单独的scope;然后在onDestroy()进行scope的cancel,相当于取消掉当前页面所有未完成的协程;最后实现一个开启协程的方法,保证我们的子类开启协程时用的都是该scope的。

class MainActivity : BaseActivity() {    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        startCoroutine(Dispatchers.Main) {            showLoadingView()            val data1 = Call().await()            val data2 = Call(data1).await()            displayData(data2)        }    }}  

在子类里就可以正常使用了,并且不用关注cancel事件。

更多相关文章

  1. Android新的网络请求框架volley源码解释及示例
  2. 以php开发服务器后台的android即时通讯app的一种实现思路
  3. 框架和流程——OkHttp 源码详解(一)
  4. Android的第二次接触
  5. 利用Fiddler对Android模拟器网络请求进行抓包【转】
  6. 2012-04-12 21:24 Android(安卓)开发中发送http请求
  7. Caffe的 Android(安卓)aar库使用(脚手架)
  8. Android(安卓)RxJava 实战系列:优雅实现 网络请求嵌套回调
  9. Android(安卓)- 小功能 使用ImageView加载本地SdCard图片和加载

随机推荐

  1. MySQL5.6 GTID模式下同步复制报错不能跳
  2. mysql学习笔记之完整的select语句用法实
  3. mysql数据表的基本操作之表结构操作,字段
  4. mysql数据库常见基本操作实例分析【创建
  5. mysql事务管理操作详解
  6. 简单了解mysql语句书写和执行顺序
  7. MySQL定时备份数据库操作示例
  8. MySQL case when使用方法实例解析
  9. mysql游标的原理与用法实例分析
  10. 简单了解MySQL union all与union的区别