最近开始用kotlin写新项目,由于后台接口调用业务成功和失败时返回的数据格式不一致,需要修改原来的网络请求封装,写个博客分享下一些kotlin扩展封装的小技巧
1. 接口格式
正常情况接口返回格式:
{
"data": {
...
},
"success":true
}
异常情况返回格式:
{
"errorCode":"1002",
"errorMsg":"账户不存在",
"success":false
}
为了统一2种数据格式,封装一个BaseResult
:
open class BaseResult<T> {
val errorCode: String = ""
val errorMsg: String = ""
val success: Boolean = false
var data: T? = null
}
每次如果调用成功则只需要data对象,如失败需要toast弹errorMsg或针对errorCode处理相应逻辑
2. 扩展封装
@POST("fshows.market.api.user.login")
fun login(@Body request: LoginRequest): Observable<BaseResult<LoginBean>>
通常在使用Rxjava+retrofit时每个接口都需要写2句重复的切换线程的方法,如果是用java语言开发我们一般可以通过compose
操作符把这2句方法封装成一个函数,而在使用kotlin时由于有扩展函数这种方便的语法糖,比java简洁很多:
fun <T> Observable<T>.dispatchDefault(): Observable<T> =
this.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
只需一句.dispatchDefault()
就完了,是不是很简单?
重点来了
回到上边的需求,那么怎么用kotlin处理接口成功和失败2中不同的数据格式呢?
如过不使用kotlin扩展的话需要用到ObservableTransformer
:
class RxStreamHelper {
fun <T> io_Main(): ObservableTransformer<BaseResult<T>, T> {
return ObservableTransformer { upstream ->
upstream.subscribeOn(Schedulers.io())
//解析data层,剔除 code /msg
.flatMap { tBaseModel ->
if (tBaseModel.success) {
Observable.just(tBaseModel.data!!)
} else Observable.error(ApiException(tBaseModel.errorCode.toInt(), tBaseModel.errorMsg))
}
.observeOn(AndroidSchedulers.mainThread())
}
}
}
而如果用扩展来写的话
fun <T> Observable<BaseResult<T>>.dispatchDefault(): Observable<T> =
this.subscribeOn(Schedulers.io())
//解析data层,剔除 code /msg
.flatMap { tBaseModel ->
if (tBaseModel.success) {
Observable.just(tBaseModel.data!!)
} else Observable.error(ApiException(tBaseModel.errorCode.toInt(), tBaseModel.errorMsg))
}
.observeOn(AndroidSchedulers.mainThread())
看了上边的代码吧,其实非常简单哈,用flatMap
操作符解析data
层的同时就完成了接口成功失败的判断
来看下api的调用代码:
ApiService.login(LoginRequest("username", MD5Utils.getStringMD5("pwd")))
.dispatchDefault()
.subscribeBy(
onNext = {
startActivity(Intent(this@LoginActivity, MainActivity::class.java))
}
)
非常简洁清爽有木有,上边的subscribeBy
是rxkotlin
库里的扩展函数,为了实现接口返回失败时弹toast我又写了个自己的扩展:
private val onNextStub: (Any) -> Unit = {}
//重写rxkotlin,全局toast异常
private val onErrorStub: (Throwable) -> Unit = { Toast.makeText(App.getContext(), it.message, Toast.LENGTH_SHORT).show() }
private val onCompleteStub: () -> Unit = {}
/**
* Overloaded subscribe function that allows passing named parameters
*/
fun <T : Any> Observable<T>.subscribeNext(
onError: (Throwable) -> Unit = onErrorStub,
onComplete: () -> Unit = onCompleteStub,
onNext: (T) -> Unit = onNextStub
): Disposable = subscribe(onNext, onError, onComplete)
把上边的subscribeBy
换成自己写的扩展subscribeNext
就ok了
结语
kotlin的扩展封装的简单应用,感谢阅读,抛砖引玉,欢迎各位交流kotlin的开发技巧
网友评论