MVVMLin网络请求封装:Retrofit+FlowAdapterFactory实现优雅API调用
【免费下载链接】MVVMLin一个基于MVVM用Kotlin+Retrofit+协程+Viewbinding+Flow来封装的快速开发框架项目地址: https://gitcode.com/gh_mirrors/mv/MVVMLin
MVVMLin是一个基于MVVM架构,采用Kotlin+Retrofit+协程+Viewbinding+Flow封装的快速开发框架。本文将详细介绍如何通过FlowAdapterFactory实现网络请求的优雅封装,帮助开发者简化API调用流程,提升代码质量与开发效率。
为什么选择Retrofit+Flow组合?
在Android开发中,网络请求是核心模块之一。传统的Callback方式容易导致"回调地狱",而Retrofit结合Kotlin Flow的响应式编程模式,能够以更简洁的代码处理异步数据流,同时提供生命周期感知能力,有效避免内存泄漏。
MVVMLin框架通过FlowAdapterFactory将Retrofit的Call对象转换为Flow数据流,实现了以下优势:
- 简化代码:用协程替代回调,代码更线性直观
- 响应式处理:支持数据变化监听与事件流操作
- 错误统一处理:集中管理网络异常与业务错误
- 生命周期感知:自动绑定UI生命周期,避免无效数据更新
FlowAdapterFactory核心实现解析
1. 适配器工厂创建
FlowAdapterFactory是连接Retrofit与Flow的桥梁,其核心作用是将Retrofit的Call对象适配为Flow数据流。关键代码位于mvvmlin/src/main/java/com/aleyn/mvvm/adapter/FlowAdapterFactory.kt:
class FlowAdapterFactory private constructor(private val async: Boolean) : CallAdapter.Factory() { override fun get(returnType: Type, annotations: Array<out Annotation>, retrofit: Retrofit): CallAdapter<*, *>? { val rawType = getRawType(returnType) if (rawType != Flow::class.java) return null // 处理Flow泛型类型 val flowType = getParameterUpperBound(0, returnType as ParameterizedType) return if (getRawType(flowType) == Response::class.java) { FlowCallAdapter(getParameterUpperBound(0, flowType as ParameterizedType), false, async) } else { FlowCallAdapter(flowType, true, async) } } companion object { @JvmStatic fun create(async: Boolean = false) = FlowAdapterFactory(async) } }该实现通过Retrofit的CallAdapter.Factory接口,检查返回类型是否为Flow,然后创建对应的FlowCallAdapter实例。
2. 网络请求执行器
FlowCallAdapter负责实际执行网络请求并转换为Flow流,实现代码位于mvvmlin/src/main/java/com/aleyn/mvvm/adapter/FlowCallAdapter.kt:
class FlowCallAdapter<R : Type>( private val responseBodyType: R, private val isBody: Boolean, private val isAsync: Boolean ) : CallAdapter<R, Flow<*>> { override fun adapt(call: Call<R>): Flow<*> { val callResponse = if (isAsync) ASyncCall(call) else SyncCall(call) return if (isBody) bodyFlow(callResponse) else responseFlow(callResponse) } private fun responseFlow(call: CallResponse): Flow<Response<*>> = flow { emit(call.call()) } private fun bodyFlow(call: CallResponse): Flow<*> = flow { val response = call.call() if (response.isSuccessful) { emit(response.body()!!) } else { throw HttpException(response) } } }核心逻辑:
- 根据isAsync参数选择同步或异步请求模式
- responseFlow:直接发射完整Response对象
- bodyFlow:仅发射响应体,并自动处理HTTP错误状态
3. 框架集成方式
在Retrofit客户端配置中添加FlowAdapterFactory,代码位于app/src/main/java/com/pcl/mvvm/utils/RetrofitClient.kt:
val retrofit = Retrofit.Builder() .baseUrl(Constant.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(FlowAdapterFactory.create(true)) .build()通过FlowAdapterFactory.create(true)启用异步请求模式,使网络请求在后台线程执行,避免阻塞主线程。
实际应用场景
1. 定义API接口
在app/src/main/java/com/pcl/mvvm/network/api/HomeService.kt中定义Flow返回类型的API:
interface HomeService { @GET("banner/json") fun getBanner(): Flow<BannerBean> @GET("article/list/{page}/json") fun getHomeList(@Path("page") page: Int): Flow<HomeListBean> }2. ViewModel中使用
在ViewModel中通过Repository调用API,并将结果转换为UI状态:
class HomeViewModel : BaseViewModel() { private val repository by lazy { HomeRepository() } val bannerData = MutableStateFlow<List<BannerBean.DataBean>>(emptyList()) fun getBanner() { launchUI { repository.getBanner().collect { bannerData.value = it.data ?: emptyList() } } } }3. UI层观察数据
在Fragment中观察ViewModel的数据变化:
class HomeFragment : BaseVMFragment<HomeViewModel>() { override fun initView() { viewModel.bannerData.observe(viewLifecycleOwner) { banners -> bannerAdapter.setList(banners) } viewModel.getBanner() } }错误处理机制
MVVMLin框架提供了统一的错误处理机制,通过ExceptionHandle.kt集中处理网络异常:
object ExceptionHandle { fun handleException(e: Throwable): ResponseThrowable { return when (e) { is HttpException -> { // 处理HTTP错误状态码 ResponseThrowable(e.code(), e.message()) } is ConnectException -> { ResponseThrowable(ERROR.NETWORK_ERROR, "网络连接失败") } // 其他异常处理... else -> { ResponseThrowable(ERROR.UNKNOWN, "未知错误") } } } }在ViewModel中通过launchUI函数自动捕获并处理异常,无需手动try-catch:
launchUI { // 异常会被自动捕获并处理 repository.getHomeList(page).collect { // 处理正常数据 } }总结与最佳实践
通过MVVMLin框架的FlowAdapterFactory实现,我们可以:
- 简化网络请求代码:用Flow替代传统Callback,减少模板代码
- 提升代码可读性:线性代码结构,更符合直觉
- 优化生命周期管理:自动绑定UI生命周期,避免内存泄漏
- 统一错误处理:集中管理各类网络异常
建议在实际项目中:
- 始终使用
launchUI函数执行网络请求,确保异常被正确处理 - 根据业务需求选择同步或异步请求模式
- 合理设计数据模型,配合Flow的操作符进行数据转换
- 在Repository层统一处理数据缓存逻辑
MVVMLin框架的网络请求封装为Android开发提供了一种优雅高效的解决方案,帮助开发者更专注于业务逻辑实现,提升应用质量与开发效率。
【免费下载链接】MVVMLin一个基于MVVM用Kotlin+Retrofit+协程+Viewbinding+Flow来封装的快速开发框架项目地址: https://gitcode.com/gh_mirrors/mv/MVVMLin
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考