最近学习了kotlin的flow,感觉和RxJava很像 于是就利用它来封装网络请求。再之前的文章中我也封装过网络请求juejin.cn/post/692263…,但是使用了flow 发现更简单。
封装的部分部分,很简单
suspend fun <T> requestFow(
showLoading: Boolean = true,
request: suspend ApiInterface.() -> BaseResponse<T>?
):Flow<BaseResponse<T>> {
if (showLoading) {
showLoading()
}
return flow {
val response = request(Api) ?: throw IllegalArgumentException("数据非法,获取响应数据为空")
if (response.errorCode != 0) {
throw ApiException(response.errorCode, response.errorMsg ?: "")
}
emit(response)
}.flowOn(Dispatchers.IO).catch {
cause -> run {
Log.e("requestFow", "==requestFow==cause==>${Thread.currentThread().name}")
toast(cause.message ?: "null")
throw cause// 这里再重新把捕获的异常再次抛出,调用的时候如果有必要可以再次catch 获取异常
}}
.onCompletion {
closeLoading()
}
}
复制代码
就这么简单 就全部完成封装了
Api:就是Retrofit的ApiInterface对象
emit: 就是把网络请求的结果回调出去
flowOn:指定运行的线程 主要是flowOn 代码前面的线程
catch: 捕获的是所有的异常,包括自定义的Api异常,这里 我把异常 默认处理 为土司然后 我又把异常 抛出去,再调用的时候会捕获到,同样使用catch捕获
onCompletion:就是请求结束的回调,包括成功和失败 这里关闭了请求对话框
然后调用collect方法获取emit回调出的结果 就是网络请求的结果
fun requestFlowData(){
viewModelScope.launch {
requestFow{
getListProject();
}.catch { cause ->
run {
Log.e("requestFow","==requestFow==cause==vm==>${cause}")
when (cause) {
is ApiException->{
}
is IOException->{
}
else->{ }
}
}
}.collect {
responseTextFlow.set(it.data.toString())
}
}
}
复制代码
requestFlowData方法就是调用网络请求,这个是再Android中的viewmodel中调用的
因为方法调用再viewModelScope.launch 中 所以catch方法和collect方法 还有onCompletion方法 都是主线程中
requestFlow:就是封装的网络请求方法
catch:就是获取抛出的异常,不获取 可不写
collect:就是获取我们想要的数据
好了 一个网络请求就封装完毕了 就这么简洁
嗯 这里 我觉得catch和collect还是写的麻烦 于是 封装一下
fun <T> Flow<T>.catch(bloc: Throwable.() -> Unit) = catch { cause -> bloc(cause) }
suspend fun <T> Flow<T>.next(bloc: suspend T.() -> Unit): Unit = collect { bloc(it) }
复制代码
这样上面的网络请求的封装就是
suspend fun <T> requestFow(
showLoading: Boolean = true,
request: suspend ApiInterface.() -> BaseResponse<T>?
):Flow<BaseResponse<T>> {
if (showLoading) {
showLoading()
}
return flow {
val response = request(Api) ?: throw IllegalArgumentException("数据非法,获取响应数据为空")
if (response.errorCode != 0) {
throw ApiException(response.errorCode, response.errorMsg ?: "")
}
emit(response)
}.flowOn(Dispatchers.IO).catch {
Log.e("requestFow","==requestFow==cause==>${Thread.currentThread().name}")
toast(message ?: "null")
throw this// 这里再重新把捕获的异常再次抛出,调用的时候如果有必要可以再次catch 获取异常
}.onCompletion {
closeLoading()
}
}
复制代码
调用的时候就是这样了
fun requestFlowData(){
viewModelScope.launch {
requestFow{
getListProject();
}.catch {
when (this) {
is ApiException->{
}
is IOException->{
}
else->{ }
}
}.next{
responseTextFlow.set(data.toString())
}
}
}
复制代码
详细的就不多说了 看demo吧,github地址:
欢迎提供意见建议
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END