Kotlin 协程之三:Android中的应用
16lz
2021-01-26
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事件。
更多相关文章
- Android新的网络请求框架volley源码解释及示例
- 以php开发服务器后台的android即时通讯app的一种实现思路
- 框架和流程——OkHttp 源码详解(一)
- Android的第二次接触
- 利用Fiddler对Android模拟器网络请求进行抓包【转】
- 2012-04-12 21:24 Android(安卓)开发中发送http请求
- Caffe的 Android(安卓)aar库使用(脚手架)
- Android(安卓)RxJava 实战系列:优雅实现 网络请求嵌套回调
- Android(安卓)- 小功能 使用ImageView加载本地SdCard图片和加载