转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/121754941
本文出自【赵彦军的博客】
系列文章推荐:
Android Flow遇见Retrofit网络请求实践
Android Kotlin协程和Retrofit结合使用
Retrofit 注解参数详解
前言
最近项目要从 Rxjava 切到 Flow ,探索最佳实践,于是就有了这篇文章
RetrofitFlowCallAdapter
添加 RetrofitFlowCallAdapter
github地址:https://github.com/zyj1609wz/RetrofitFlowCallAdapter
//添加maven地址
allprojects {
repositories {
maven { url 'https://jitpack.io' }
}
}
//添加依赖
implementation 'com.github.zyj1609wz:RetrofitFlowCallAdapter:1.1.0'
在 Retrofit 初始化的时候加入:
val retrofit = Retrofit.Builder()
.baseUrl("https://api.github.com")
.addCallAdapterFactory(FlowCallAdapterFactory.createAsync())
.addConverterFactory(GsonConverterFactory.create())
.build()
定义接口
interface ApiService {
//返回 Body
@GET("users/{user}/repos")
fun listReposWithBody(@Path("user") user: String): Flow<List<Repo>>
//返回 Response
@GET("users/{user}/repos")
fun listReposWithResponse(@Path("user") user: String): Flow<Response<List<Repo>>>
}
创建 ApiService 实例:
private val service: ApiService = retrofit.create(ApiService::class.java)
使用姿势一:
lifecycleScope.launch {
service.listReposWithResponse("zyj1609wz")
.flowOn(Dispatchers.IO)
.catch {
//处理异常
it.printStackTrace()
}
.collect {
//处理结果
val list = it.body()
}
}
使用姿势二:使用 flow 的 launchIn
函数可以进一步简化
service.listReposWithBody("zyj1609wz")
.catch {
//处理异常
it.printStackTrace()
}
.onEach {
//处理结果
val item = it[0]
}
.launchIn(lifecycleScope)
.start()
自定义flow 构建类
首先创建函数的自定义 Flow
构建工具类
fun <T> getFlow(block: suspend () -> T): kotlinx.coroutines.flow.Flow<T> {
return flow {
emit(block())
}
}
ApiService 的挂起接口声明
interface ApiService {
@GET("users/{user}/repos")
suspend fun listReposWithBody(@Path("user") user: String): List<Repo>
}
使用:
getFlow {
service.listReposWithBody("zyj1609wz")
}
.catch {
it.printStackTrace()
}
.onEach {
val item = it[0]
}
.launchIn(lifecycleScope)
.start()
Flow多个请求合并
合并请求 zip
//第一个网络请求
val request1 = getFlow {
service.listReposWithBody("zyj1609wz")
}
//第二个网络请求
val request2 = getFlow {
service.listReposWithBody("zyj1609wz")
}
//两个请求并行
request1.zip(request2) { response1, response2 ->
Pair(response1, response2)
}
.catch {
it.printStackTrace()
}
.onEach {
val list1 = it.first
val list2 = it.second
}
.launchIn(lifecycleScope)
.start()
如果是两个请求合并,那么用 zip 操作符就行了。但是 zip 也有一个问题,只支持两个请求并行。如果是3个请求,或者更多的请求,就需要用到 combine
合并请求 combine
//第一个网络请求
val request1 = getFlow {
service.listReposWithBody("zyj1609wz")
}
//第二个网络请求
val request2 = getFlow {
service.listReposWithBody("zyj1609wz")
}
//第三个网络请求
val request3 = getFlow {
service.listReposWithBody("zyj1609wz")
}
//3个请求并行
combine(request1, request2, request3) { response1, response2, response3 ->
//合并结果
mutableListOf(response1, response2, response3)
}
.catch {
//处理异常
it.printStackTrace()
}
.onEach {
//处理结果
}
.launchIn(lifecycleScope)
.start()
Flow网络重试 retryWhen
retryWhen { cause, attempt ->
//attempt是重试次数,从0开始
//返回值是 boolean 类型,true 继续重试,false 停止重试
attempt < 2
}
下面我们写一个重试两次的场景
getFlow {
service.listReposWithBody("zyj1609wz")
}.retryWhen { cause, attempt ->
attempt < 2
}.catch {
//处理异常
}.onEach {
//处理结果
}.launchIn(lifecycleScope)
.start()