这代码,你不包装下?

简介: 不管做什么事情,我们都要有一颗上进的心,写代码也是如此。最开始要写得出,然后要写得对,然后要写得又对又好,最后再追求那个传说中的快。

不管做什么事情,我们都要有一颗上进的心,写代码也是如此。最开始要写得出,然后要写得对,然后要写得又对又好,最后再追求那个传说中的快。


当然,现在好用又强大的三方库越来越多了,业务开发渐渐的变成 api boy 了。当然,api boy 亦有差距,就看你能不能把 api 封装得足够好用了。


今天,我来教教你们如何用协程包装下微信分享的接口。


首先看看微信分享接口,它的发送数据接口和接收接口是分开的。


发送请求为:

fun shareToWx(msg: WXMediaMessage, transaction: String){
  val req = SendMessageToWX.Req()
  // 唯一标示一个请求, 用于微信返回的回调使用
  req.transaction = transaction
  // 调用 api 接口,发送数据到微信
  api.sendReq(req)
}

然后跳转到微信,微信处理完后,会调起 WXEntryActivity ,通过 onResp 去接收消息:

class WXEntryActivity() : AppCompatActivity(), IWXAPIEventHandler{
    override fun onResp(baseResp: BaseResp) {
        // 通过 baseResp.transaction 去 match 请求
        // TODO handle the baseResp
        finish()
    }
}

整个流程清晰,就是请求和回应分离了,虽然有 transaction 去追踪请求连,但我也见过完全不用这个参数的开发,而是做了个假设:短时间必定只有一次分享,而且回应应该也很快,所以从微信收到的结果必定是当前界面分享的。。。(反正一般跑起来都是正常的。)


更多高明的开发可能就会用上 EventBus 了,把 resp 抛到 EventBus 里,然后业务自己去监听 EventBus 里的消息,然后处理。


这样也不是不可以,但总归一条业务链下来,代码要写在两个地方,维护起来也不是很爽,而且每次还要去关注那个 transaction 参数。


那该怎么包装呢?RxJavaRxJava 的包装,协程有协程的包装,但大体思路应该一样。

总之我们要善于利用新的工具去让这个世界变得更美好。对于我,我当然是选择更现代的协程了。


代码如下:

private val wxMsgChannelMap = HashMap<String, Channel<BaseResp>>()
// 入口方法
suspend fun shareToWx(msg: WXMediaMessage): BaseResp {
    val req = SendMessageToWX.Req()
  // 构造唯一标示,仅内部使用
  req.transaction = System.currentTimeMillis().toString()
  // 构建一个缓存一个结果的 channel
  val channel = Channel<BaseResp>(1)
  return withContext(Dispatchers.Main) {
       // 将 channel 存储起来
       wxMsgChannelMap[transaction] = channel
       try {
           // 调用 api 接口,发送数据到微信
           api.sendReq(req)
           // 协程等待 channel 的结果
           channel.receive()
       } finally {
           channel.close()
           wxMsgChannelMap.remove(transaction)
       }
  }
}
class WXEntryActivity() : AppCompatActivity(), IWXAPIEventHandler{
    override fun onResp(baseResp: BaseResp) {
         AppScope.launch(Dispatchers.Main) {
            // 从 map 中寻找到对应的 channel
            val channel = wxMsgChannelMap[baseResp.transaction] ?: return@launch
            if (channel.isClosedForSend || channel.isClosedForReceive) {
                return@launch
            }
            // 向 channel 发送数据
            channel.send(baseResp)
        }
        finish()
    }
}

上面的代码,其实很简单,就是借助了 channel 而已,但只要有这一层封装,业务放就可以将逻辑写得简洁明了了:

val msg = WXMediaMessage(...) // 构造消息
val result = shareToWx(msg)
// 处理结果

是不是看上去就清爽多了?那可不可以做得更好呢? 我们必须要在工程中的特定目录下新建 WXEntryActivity, 然后各个 app 里面的代码都是非常雷同,所以,我们能不能搞个库,把它给封装并隐藏起来?就可以造福更多的开发?WXEntryActivity 要求特定目录,那是不是只能动态生成? ksp 是不是就可以上场装逼了?


问:那继续搞下去吗?


答:不搞,现在的又不是不能用。

目录
相关文章
|
Java 关系型数据库 MySQL
flea-db使用之JPA封装介绍
【4月更文挑战第3天】本篇 Huazie 介绍 Flea 框架下的 flea-db模块中的 JPA 封装代码
167 6
flea-db使用之JPA封装介绍
|
Web App开发 移动开发 f2etest
F2etest 多浏览器兼容性测试整体解决方案。
F2etest是一个面向前端、测试、产品等岗位的多浏览器兼容性测试整体解决方案。
F2etest  多浏览器兼容性测试整体解决方案。
各台平台电商API接口吊桶,API接口分类
各台平台电商API接口吊桶,API接口分类
|
网络安全
《阿里云产品手册2022-2023 版》——DDoS 防护
《阿里云产品手册2022-2023 版》——DDoS 防护
211 0
|
存储 分布式计算 负载均衡
考研408系列--计算机网络(计算机网络概述)
考研408系列--计算机网络(计算机网络概述)
210 0
C/C++编程题之字符串排序
C/C++编程题之字符串排序
|
设计模式 存储 安全
iOS Principle:Singleton
iOS Principle:Singleton
183 0
iOS Principle:Singleton
产品经理又开始为难我了???我。。。。(一)
前言 大家好,我是Fly哥。最近做项目的时候,就是产品经理给的图总是很大,不压缩。每天要处理这些图片真的很累哇。于是一怒之下写下了这个「vscode 插件」。「插件核心功能是压缩,然后上传图片」。压缩的网站其实就是「tinypng」 这个网站然后图片压缩后,然后再上传到cdn上,然后然后这个压缩过的url 直接放到我们的粘贴板上。下面跟着我的步伐一步一步来写实现它。先看效果图: 图片 效率对比 开发这个主要是提高团队开发效率, 绝不是为了炫技。看图: 图片 image-20211017224316386 image-20211017224316386 需求分析 可在vscodde的set
产品经理又开始为难我了???我。。。。(一)
SAP MM MIRO的时候,发票价格与物料主数据的价格(移动平均价)有差异的处理
SAP MM MIRO的时候,发票价格与物料主数据的价格(移动平均价)有差异的处理
SAP MM MIRO的时候,发票价格与物料主数据的价格(移动平均价)有差异的处理