Kotlin中像RxHttp一样优雅的使用Retrofit
1.简介
Retrofit对协程的支持非常的简陋。在kotlin中使用不符合kotlin的优雅。 RxHttp在协程中使用非常方便。但是我们项目又已经使用了Retrofit怎么办,那就让Retrofit像RxHttp一样使用 RxHttp
2.源码地址
3.本框架使用
添加依赖
implementation "io.github.cnoke.ktnet:api:?"
写一个网络请求数据基类
open class ApiResponse<T>(
var data: T? = null,
var errorCode: String = "",
var errorMsg: String = ""
)
实现com.cnoke.net.factory.GsonResponseBodyConverter
class MyGsonResponseBodyConverter : GsonResponseBodyConverter() {
override fun convert(value: ResponseBody): Any {
val jsonReader = gson.newJsonReader(value.charStream())
val data = adapter.read(jsonReader) as ApiResponse<*>
val t = data.data
val listData = t as? ApiPagerResponse<*>
if (listData != null) {
//如果返回值值列表封装类,且是第一页并且空数据 那么给空异常 让界面显示空
if (listData.isRefresh() && listData.isEmpty()) {
throw ParseException(NetConstant.EMPTY_CODE, data.errorMsg)
}
}
// errCode 不等于 SUCCESS_CODE,抛出异常
if (data.errorCode != NetConstant.SUCCESS_CODE) {
throw ParseException(data.errorCode, data.errorMsg)
}
return t!!
}
}
进行网络请求
interface TestServer {
@GET("banner/json")
suspend fun awaitBanner(): Await<List<Banner>>
}
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(HeadInterceptor())
.addInterceptor(LogInterceptor())
.build()
/**
* 必须使用ApiResultCallAdapterFactory()
* GsonConverterFactory.create(ApiResponse::class.java,MyGsonResponseBodyConverter())
* GsonConverterFactory.create传入网络请求数据结构基类,以及数据解析类
*/
val retrofit = Retrofit.Builder()
.client(okHttpClient)
.baseUrl("https://www.wanandroid.com/")
.addCallAdapterFactory(ApiResultCallAdapterFactory())
.addConverterFactory(GsonConverterFactory.create(ApiResponse::class.java,MyGsonResponseBodyConverter()))
.build()
val service: TestServer = retrofit.create(TestServer::class.java)
lifecycleScope.launch {
val banner = service.awaitBanner().await()
}
异步请求同步请求,异常捕获参考如下try开头的会捕获异常,非try开头不会捕获。 其他各种用法请参考RxHttp 操作符使用(目前暂不支持文件下载,文件上传) RxHttp 2000+star,协程请求,仅需三步 - 掘金 (juejin.cn)
fun banner(){
lifecycleScope.launch {
//单独处理异常 tryAwait会处理异常,如果异常返回空
val awaitBanner = service.awaitBanner().tryAwait()
awaitBanner?.let {
for(banner in it){
Log.e("awaitBanner",banner.title)
}
}
/**
* 不处理异常 异常会直接抛出,统一处理
*/
val awaitBannerError = service.awaitBanner().await()
}
}
/**
* 串行 await
*/
fun serial(){
lifecycleScope.launch {
//先调用第一个接口await
val awaitBanner1 = service.awaitBanner().await()
//第一个接口完成后调用第二个接口
val awaitBanner2 = service.awaitBanner().await()
}
}
/**
* 并行 async
*/
fun parallel(){
lifecycleScope.launch {
val awaitBanner1 = service.awaitBanner().async(this)
val awaitBanner2 = service.awaitBanner().async(this)
//两个接口一起调用
awaitBanner1.await()
awaitBanner2.await()
}
}