背景

异步回调的方式虽然实现了需求,但是牺牲了可读性,过多的回调让代码变得难以维护.

解决思路

rxjava->协程

Java语言开发的时候,可以借助一些第三方库如RxJava,来让减少嵌套. 但是实际落地的效果并不理想, 因为不能保证团队里面每个人都擅长并且能够接受Rx的风格.

在使用kotlin协程的时候我发现了新世界.

协程+流式设计

我的需求是实现一个订阅功能,并将功能模块化后提供给其他产品线.

外部调用

外部调用者传入一个id,sdk告诉外部购买成功还是发生异常.

内部实现

内部实现大体上是以上6步. 但是这里每一步都是异步的,如果用java实现,免不了处理很多回调代码.

我尝试使用kotlin+协程完成,发现出奇的简单易读.

// 偷懒 构造一个Activity的扩展方法,反正最后是以Activity的方式来提供出去

fun Activity.goSubscript(productID: String, exceptionHandler: CoroutineExceptionHandler) =

CoroutineScope(Dispatchers.Main).launch(exceptionHandler) {

SubscriptHelper(this@goSubscript).run {

// 1

init()

// 2

getAvailableHistory()?.let { purchase ->

if (checkPurchase(purchase)) {

return@launch;

}

}

// 3

val skuDetails = getAvailableProducte(productID)

// 4

val purchase = subscriptProducte(this@goSubscript, skuDetails)

// 5

val isCheckedSuccess = checkPurchase(purchase)

// 6

if (!isCheckedSuccess) {

val acknowSuccess = acknowledgePurchase(purchase)

logd(content = "客户端确认${if (acknowSuccess) "成功" else "失败"} ");

}

}

}

复制代码

体会了下kotlin的协程代码风格,这大概就是Kotlin的魅力吧. 那么怎么来实现上诉风格的代码呢?

这里大概需要有两个问题要解决:

怎么把Java异步回调转化成suspend函数.

怎么处理java回调哪些异常场景.

把回调转化成suspend函数

解决办法:利用通道

使用suspendCoroutine

// 1. 建立和GP/AppStore的连接

suspend fun init(): Boolean = try {

withTimeout(1500) {

suspendCoroutine { continuation ->

billingClient =

BillingClient.newBuilder(context).setListener(listenerUpdate)

.enablePendingPurchases()

.build()

.apply {

startConnection {

onBillingSetupFinishedFun {

continuation.resume(true)

}

}

};

}

}

} catch (e: TimeoutCancellationException) {

throw InitException()

}

复制代码

看上面这个初始化的栗子,先构造了一个withTimeout协程代码块,然后 在suspendCoroutine代码块会生成一个continuation参数,在onBillingSetupFinishedFun函数回调的时候,我们直接使用这个参数来发送消息,结束挂起.

例如成功的时候返回

continuation.resume(true)

复制代码

异常的时候可以

continuation.resumeWithException()

复制代码使用channel

有的情况下回调不是通过callback完成的,例如使用Handler机制完成的回调代码,怎么转化成协程.

var channel: Channel = Channel();

// 利用channel发送

var listenerUpdate: PurchasesUpdatedListener = object : PurchasesUpdatedListener {

override fun onPurchasesUpdated(

billingResult: BillingResult?,

purchases: MutableList?

) {

CoroutineScope(Dispatchers.Main).launch {

purchases?.let {

if (it.size >= 0) {

purchase = it[0]

}

}

channel.send(billingResult!!)

channel.close()

}

}

};

// 利用channel接收

suspend fun subscriptProducte(activity: Activity, skuDetails: SkuDetails): Purchase {

billingClient.launchBillingFlow(

activity,

BillingFlowParams.newBuilder().setSkuDetails(skuDetails).build()

)

val result = channel.receive()

when (result.responseCode) {

BillingClient.BillingResponseCode.OK -> {

return purchase!!

}

BillingClient.BillingResponseCode.USER_CANCELED -> {

throw UserCancleException()

}

else -> {

throw SubscriptProductException(result.debugMessage)

}

}

}

复制代码

也就是说channel可以单独出来作为一个对象使用.

协程异常处理

上面的调用函数设计的时候,我构造了一个参数exceptionHandler,用作整个事件的异常处理.

fun Activity.goSubscript(productID: String, exceptionHandler: CoroutineExceptionHandler) =

CoroutineScope(Dispatchers.Main).launch(exceptionHandler) {

复制代码

然后我定义了一些异常类型

class InitException(msg: String = "") : Exception()

class RepeateSubscription(msg: String = "") : Exception()

class NoProducteException(msg: String = "") : Exception()

class UserCancleException(msg: String = "") : Exception()

class SubscriptProductException(msg: String = "") : Exception()

class AcknowException(msg: String = "") : Exception()

复制代码

然后当内部出现购买失败的回调的时候,主动抛出一个异常,把整个事件流中断,外部处理这些异常也很简单,直接定义一个exceptionHandler(是个参数是throwable的函数)对象接收.

总结起来就是:

通过抛出异常来中断事件流

异常在协程内部会向上传导

外部开辟一个协程任务的时候,可以给内部指定一个异常处理器

总结

看过一些讲协程的文章,大多都是讲一些原理和API的使用,总感觉没有吸引到让我觉得他比线程模式更好,然后自己摸索着在项目中写了一次.

大概这就是 纸上得来终觉浅,绝知此事要躬行吧.

Android开发,为什么要用Kotlin而不是Java

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[[Kotlin协程] 回调地狱的一种解决思路]http://www.zyiz.net/tech/detail-139988.html

android kotlin 回调,[Kotlin协程] 回调地狱的一种解决思路相关推荐

  1. 【Kotlin 协程】协程简介 ( 协程概念 | 协程作用 | 创建 Android 工程并进行协程相关配置开发 | 异步任务与协程对比 )

    文章目录 一.协程概念 二.协程作用 三.创建 Android 工程并进行协程相关配置 1.创建 Android 工程 2.配置协程环境 3.布局文件 4.异步任务代码示例 5.协程代码示例 6.完整 ...

  2. 关于C10K、异步回调、协程、同步阻塞

    2019独角兽企业重金招聘Python工程师标准>>> 最近到处在争论这些话题,发现很多人对一些基础的常识并不了解,在此发表一文做一下解释.此文未必能解答所有问题,各位能有一个大致的 ...

  3. 并发编程之进程池,线程池 和 异步回调,协程

    1.进程池和线程池 2.异步回调 3.协程 4.基于TCP使用多线程实现高并发 一.进程池和线程池 什么是进程池和线程池: ''' 池 Pool 指的是一个容器 线程池就是用来存储线程对象的 容器创建 ...

  4. 同步与异步,回调与协程

    目录 概念上下文: 同步的方式: 异步加回调的方式: 异步协程方式: 总结: 这里分享一个 协程原理到实现,全局分析丨协程的切换与调度视频点击查看:「链接」 正文 本文主要介绍在网络请求中的同步与异步 ...

  5. Unity 协程回调

    按照顺序Debug,1-5进行 //按照1-5顺序 //---------------------------------------------------- StartCoroutine(func ...

  6. Android kotlin实战之协程suspend详解与使用

    前言 Kotlin 是一门仅在标准库中提供最基本底层 API 以便各种其他库能够利用协程的语言.与许多其他具有类似功能的语言不同,async 与 await 在 Kotlin 中并不是关键字,甚至都不 ...

  7. Android使用suspendCancellableCoroutine将回调转换为协程

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/122058124 本文出自[赵彦军的博客] 文章目录 suspendCancella ...

  8. go 协程回调函数 传入参数_ECMAScript 6 入门教程—Generator 函数的异步应用

    作者 | 阮一峰异步编程对 JavaScript 语言太重要.JavaScript 语言的执行环境是"单线程"的,如果没有异步编程,根本没法用,非卡死不可.本章主要介绍 Gener ...

  9. Retrofit+kotlin Coroutines(协程)+mvvm(Jetpack架构组件)实现更简洁的网络请求

    前言 使用kotlin协程也有一段时间了,给我最大的感受就是完全可以替代Rxjava了,并且写起来更加的简洁. 6月份Retrofit发布的2.6.0版本内部支持了kotlin协程中的挂起(suspe ...

最新文章

  1. Bug: CuteEditor与IE8不兼容
  2. 用电脑发短信_丢掉你的手机数据线吧!用这个软件轻松在任何设备互传文件
  3. 【Lucene4.8教程之四】分析
  4. docker-compose观察实时日志_大数据项目实战之在线教育(03实时需求) - 十一vs十一...
  5. c语言字符串文库总结,C语言程序设计入门:字符串函数
  6. 输出结果 配置_经典架构新玩法:用单端仪表放大器实现全差分输出
  7. QRCode二维码生成方案及其在带LOGO型二维码中的应用(2)
  8. 华邦电子2022年1月营收为新台币86.90亿元
  9. Java8函数式编程详解
  10. Android 获取联系人列表
  11. 《MYSQL必知必会》—2.MySQL简介
  12. git 创建和合并分支
  13. 高通SDX12:sar sensor AW9610x驱动移植
  14. intel cpu core/“酷睿”系列发展史,供组装机的朋友们参考
  15. java 拉勾网,拉钩网java笔试题分享
  16. 转 主流蓝牙BLE控制芯片详解(5):Dialog DA14580
  17. JAVA面试大全(持续更新中...)
  18. android 银联支付必须要nfc吗,手机没有NFC功能,可以使用银联云闪付功能吗?
  19. Kafka基于Zookeeper搭建高可用集群实战
  20. svn 合并分支 idea

热门文章

  1. Audacity丰富的插件支持,果然强大!
  2. 股市大跌下的逆向思维
  3. 对Python生成器的理解
  4. npm 设置淘宝源还原官网源
  5. 改进:2-inception of Self attention-Stacking LSTM 新型网络模型介绍与编程实现
  6. 大连理工大学中文情感词汇本体库(含情绪分析代码)
  7. 使用C语言实现各种排序(总结)
  8. 三星电子全球最大半导体生产线开始量产;飞利浦家居照明发布年度家装风格指南 | 美通企业日报...
  9. 如何用matlab自动发邮件,用matlab发送邮件
  10. Java反射常用命令