Android Flow遇见Retrofit网络请求实践

转载请标明出处: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()
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值