MVVM 架构和MVI架构的优缺点对比

Jetpack MVVM 架构讲解

MVVM(Model-View-ViewModel)架构是 Android 开发中一种常用的架构模式,利用 Android Jetpack 组件,可以更简洁和高效地实现 MVVM。以下是 MVVM 的各个组件及其职责:

  1. Model

    • 职责:处理数据逻辑,包括从网络或数据库获取数据。
    • 示例 :使用 Room 数据库、网络请求库(如 Retrofit)等来实现数据获取和存储。
  2. View

    • 职责:展示 UI 并响应用户交互。View 直接绑定到 ViewModel,并观察 LiveData 的变化。
    • 示例:Activity、Fragment、XML 布局文件。
  3. ViewModel

    • 职责:为 View 提供数据,处理与 UI 相关的逻辑,确保配置更改(如屏幕旋转)不会丢失数据。
    • 示例 :使用 LiveData 来保存数据并通知 View 更新。
示例代码
kotlin 复制代码
// Model
@Entity(tableName = "user")
data class User(
    @PrimaryKey val id: Int,
    val name: String
)

@Dao
interface UserDao {
    @Query("SELECT * FROM user WHERE id = :userId")
    fun getUserById(userId: Int): LiveData<User>
}

@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao(): UserDao
}

// ViewModel
class UserViewModel(application: Application) : AndroidViewModel(application) {
    private val userDao: UserDao = AppDatabase.getDatabase(application).userDao()
    private val _userId = MutableLiveData<Int>()

    val user: LiveData<User> = Transformations.switchMap(_userId) { id ->
        userDao.getUserById(id)
    }

    fun setUserId(id: Int) {
        _userId.value = id
    }
}

// View (Activity)
class UserActivity : AppCompatActivity() {
    private lateinit var userViewModel: UserViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_user)

        userViewModel = ViewModelProvider(this).get(UserViewModel::class.java)

        userViewModel.user.observe(this, Observer { user ->
            // 更新 UI
            findViewById<TextView>(R.id.userName).text = user.name
        })

        // 设置用户 ID 以触发数据加载
        userViewModel.setUserId(1)
    }
}

MVI 架构讲解

MVI(Model-View-Intent)是另一种架构模式,特别强调单一数据流和不可变状态。MVI 的核心思想是通过 Intent 驱动状态变化,并用单一的状态对象来描述整个 UI。

  1. Model

    • 职责:处理数据逻辑,包括从网络或数据库获取数据,类似 MVVM。
  2. View

    • 职责:展示 UI 并响应用户交互,渲染单一的状态对象。
    • 示例:Activity、Fragment、XML 布局文件。
  3. Intent

    • 职责:用户意图的封装,触发状态变化。
    • 示例:点击按钮、输入文本等用户操作。
  4. State

    • 职责:表示 UI 的单一状态。
    • 示例:数据类包含所有 UI 所需的数据。
示例代码
kotlin 复制代码
// State
data class UserState(
    val user: User? = null,
    val isLoading: Boolean = false,
    val error: String? = null
)

// Intent
sealed class UserIntent {
    data class LoadUser(val userId: Int) : UserIntent()
}

// ViewModel
class UserViewModel : ViewModel() {
    private val _state = MutableLiveData<UserState>()
    val state: LiveData<UserState> get() = _state

    fun processIntent(intent: UserIntent) {
        when (intent) {
            is UserIntent.LoadUser -> loadUser(intent.userId)
        }
    }

    private fun loadUser(userId: Int) {
        _state.value = UserState(isLoading = true)
        // 假设 repository 获取用户数据
        repository.getUserById(userId, object : Callback<User> {
            override fun onSuccess(user: User) {
                _state.value = UserState(user = user)
            }

            override fun onError(error: String) {
                _state.value = UserState(error = error)
            }
        })
    }
}

// View (Activity)
class UserActivity : AppCompatActivity() {
    private lateinit var userViewModel: UserViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_user)

        userViewModel = ViewModelProvider(this).get(UserViewModel::class.java)

        userViewModel.state.observe(this, Observer { state ->
            // 渲染 UI
            if (state.isLoading) {
                // 显示加载中
            } else if (state.user != null) {
                findViewById<TextView>(R.id.userName).text = state.user.name
            } else if (state.error != null) {
                // 显示错误信息
            }
        })

        // 发送 Intent 加载用户数据
        userViewModel.processIntent(UserIntent.LoadUser(1))
    }
}

MVVM 和 MVI 对比

MVVM 的优缺点

优点

  • 简单易理解,易于上手。
  • 更接近传统的 Android 开发模式,使用 Jetpack 组件可以简化开发。
  • ViewModel 与 View 之间通过数据绑定和 LiveData 实现解耦,代码简洁。

缺点

  • 如果没有严格遵守单向数据流,可能导致状态管理混乱。
  • ViewModel 可能会变得复杂,包含过多逻辑。
MVI 的优缺点

优点

  • 强调单一数据流和不可变状态,易于调试和测试。
  • 状态集中管理,UI 只需渲染状态,逻辑清晰。
  • Intent 和 State 的分离,使得代码更加模块化。

缺点

  • 对于简单的应用可能显得过于复杂。
  • 状态对象可能会变得非常庞大,管理起来比较麻烦。
  • 学习曲线较陡,特别是对不熟悉函数式编程和不可变状态的开发者。
总结
  • MVVM 更适合大多数传统的 Android 开发场景,特别是中小型项目,简单易用,结合 Jetpack 组件可以提高开发效率。
  • MVI 更适合复杂的应用,特别是需要严格状态管理和单一数据流的项目,尽管初始学习成本较高,但在维护和扩展上具有优势。

选择哪种架构模式,取决于项目的复杂度、团队的熟悉程度以及具体的需求。综合考虑这些因素,可以做出更适合的架构选择。
联系我

相关推荐
扑兔AI1 小时前
B2B销售线索挖掘效率提升的技术实践:基于工商公开数据的客源筛选与竞品分析架构
大数据·人工智能·架构
用户7488312788854 小时前
从LangChain 到LangGraph 全解析
架构
heimeiyingwang6 小时前
【架构实战】设计一个日志分析平台(ELK架构)
elk·架构·linq
企业架构师老王6 小时前
货物入库分类混乱与库位规划难题:基于实在Agent的非侵入式仓储架构演进指南
人工智能·ai·架构
生成论实验室7 小时前
《源·觉·知·行·事·物:生成论视域下的统一认知语法》第十七章 科学与人心的重聚
人工智能·算法·架构·知识图谱·创业创新
从零开始学习人工智能7 小时前
一文读懂Safous网关+POP架构:零信任ZTNA完整工作原理(请求+响应全流程)
服务器·网络·架构
不懂的浪漫7 小时前
Netty 不只是 TCP 框架:它解决的是高并发业务系统的组织问题
网络·网络协议·tcp/ip·架构·netty
千帆_Evan8 小时前
agent使用初体验
架构
小短腿的代码世界9 小时前
Qt事件驱动高频交易引擎架构:从事件循环到零延迟通信的完整实现
qt·架构
skilllite作者10 小时前
Deer-Flow 工作流引擎深度评测报告
java·大数据·开发语言·chrome·分布式·架构·rust