Jetpack Compose 架构如何选?MVP 、 MVVM 还是 MVI?

本文探讨了在Jetpack Compose中选择合适架构的问题,通过一个简单的Wanandroid搜索功能为例,比较了MVP、MVVM(不依赖Jetpack)和MVI模式。在Compose中,MVP因无法获取UI引用而不适用,MVVM与Compose的工作方式契合,而MVI则更强调数据的单向流动和唯一数据源,类似于MVVM+Redux。作者建议,对于Compose项目,MVI可能是最佳选择,但已有MVVM项目的迁移成本较低。文章还提到了Clean Architecture在大型项目中的应用,以及如何在Compose中处理页面路由和状态管理。
摘要由CSDN通过智能技术生成

本次 I/O 大会上曝出了 Compose 1.0 即将发布的消息,虽然 API 层面已趋于稳定,但真正要在项目中落地还少不了一套合理的应用架构。传统 Android 开发中的 MVP、MVVM 等架构在声明式UI这一新事物中是否还依旧可用呢?

本文以一个简单的业务场景为例,试图找出一种与 Compose 最契合的架构模式

Sample : Wanandroid Search

App基本功能:用户输入关键字,在 wanandroid 网站中搜索出相关内容并展示

功能虽然简单,但是集合了数据请求、UI展示等常见业务场景,可用来做UI层与逻辑层的解耦实验。

前期准备:Model层

其实无论 MVX 中 X 如何变化, Model 都可以用同一套实现。我们先定义一个 DataRepository ,用于从 wanandroid 获取搜索结果。后文Sample中的 Model 层都基于此 Repo 实现

@ViewModelScoped
class DataRepository @Inject constructor(){

    private val okhttpClient by lazy {
        OkHttpClient.Builder().build()
    }

    private val apiService by lazy {
        Retrofit.Builder()
            .baseUrl("https://www.wanandroid.com/")
            .client(okhttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build().create(ApiService::class.java)
    }

    suspend fun getArticlesList(key: String) =
        apiService.getArticlesList(key)
}

Compose为什么需要架构?

首先,先看看不借助任何架构的 Compose 代码是怎样的?

不使用架构的情况下,逻辑代码将与UI代码耦合在一起,在Compose中这种弊端显得尤为明显。常规 Android 开发默认引入了 MVC 思想,XML的布局方式使得UI层与逻辑层有了初步的解耦。但是 Compose 中,布局和逻辑同样都使用Kotlin实现,当布局中夹了杂逻辑,界限变得更加模糊。

此外,Compose UI中混入逻辑代码会带来更多的潜在隐患。由于 Composable 会频繁重组,逻辑代码中如果涉及I/O 就必须当做 SideEffect{} 处理、一些不能随重组频繁创建的对象也必须使用 remember{} 保存,当这些逻辑散落在UI中时,无形中增加了开发者的心智负担,很容易发生遗漏。

Sample 的业务场景特别简单,UI中出现少许 remember{} 、LaunchedEffect{} 似乎也没什么不妥,对于一些相对简单的业务场景出现下面这样的代码没有问题:

@Composable
fun NoArchitectureResultScreen(
    answer: String
) {

    val isLoading = remember { mutableStateOf(false) }

    val dataRepository = remember { DataRepository() }

    var result: List<ArticleBean> by remember { mutableStateOf(emptyList()) }

    LaunchedEffect(Unit) {
        isLoading.value = true
        result = withContext(Dispatchers.IO) { dataRepository.getArticlesList(answer).data.datas }
        isLoading.value = false
    }

    SearchResultScreen(result, isLoading.value , answer)

}

但是,当业务足够复杂时,你会发现这样的代码是难以忍受的。这正如在 React 前端开发中,虽然 Hooks 提供了处理逻辑的能力,但却依然无法取代 Redux。

Android中的常见架构模式

MVPMVVMMVI 是 Android中的而一些常见架构模式,它们的目的都是服务于UI层与逻辑层的解耦,只是在解耦方式上有所不同,如何选择取决于使用者的喜好以及项目的特点

“没有最好的架构,只有最合适的架构。”

那么在 Compose 项目中何种架构最合适呢?

MVP


MVP 主要特点是 Presenter 与 View 之间通过接口通信, Presenter 通过调用 View 的方法实现UI的更新。

这要求 Presenter 需要持有一个 View 层对象的引用,但是 Compose 显然无法获得这种引用,因为用来创建 UI 的 Composable 必须要求返回 Unit,如下:

@Composable
fun HomeScreen() {
    Column {
        Text("Hello World!")
    }
}

官方文档中对无返回值的要求也进行了明确约束:

The function doesn’t return anything. Compose functions that emit UI do not need to return anything, because they describe the desired screen state instead of constructing UI widgets. https://developer.android.com/jetpack/compose/m

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值