Android MVI 架构

715 阅读2分钟

Android MVI架构是一种基于单向数据流和不可变状态的架构模式,通过明确职责划分和状态集中管理简化复杂UI逻辑。以下是核心要点及实现示例:


一、架构核心组成

  1. Model(状态容器)
    通过不可变数据类描述UI所有可能状态(如加载、成功、错误),实现唯一可信数据源。例如:

    
    data class LoginState(
        val isLoading: Boolean = false,
        val isSuccess: Boolean = false,
        val error: String? = null
    )
    
  2. View(UI层)
    被动渲染Model状态,将用户操作封装为Intent发送至ViewMode。例如:

    
    class LoginActivity : AppCompatActivity() {
        private val viewModel: LoginViewModel by viewModels()
        override fun onCreate(savedInstanceState: Bundle?) {
            // 观察状态变化
            viewModel.state.observe(this) { state ->
                when {
                    state.isLoading -> showLoading()
                    state.isSuccess -> navigateToHome()
                    state.error != null -> showError(state.error)
                }
            }
            // 发送Intent
            binding.loginButton.setOnClickListener {
                viewModel.process(LoginIntent.Submit(
                    username = binding.etUsername.text.toString(),
                    password = binding.etPassword.text.toString()
                ))
            }
        }
    }
    
  3. Intent(用户意图)
    用密封类定义所有可能的用户操作事件:

    sealed class LoginIntent {
        data object Init : LoginIntent()
        data class Submit(val username: String, val password: String) : LoginIntent()
        data class ResetPassword(val email: String) : LoginIntent()
    }
    
  4. ViewModel(逻辑处理器)
    接收Intent后处理业务逻辑,通过响应式流更新状态:

    class LoginViewModel : ViewModel() {
        private val _state = MutableStateFlow(LoginState())
        val state: StateFlow<LoginState> = _state.asStateFlow()
        
        fun process(intent: LoginIntent) {
            when (intent) {
                is LoginIntent.Submit -> {
                    _state.update { it.copy(isLoading = true) }
                    viewModelScope.launch {
                        repository.login(intent.username, intent.password)
                            .onSuccess { _state.update { it.copy(isLoading = false, isSuccess = true) } }
                            .onFailure { _state.update { it.copy(isLoading = false, error = it.message) } }
                    }
                }
                // 其他Intent处理...
            }
        }
    }
    

二、数据流动机制

  1. 单向数据流
    用户操作 → Intent → ViewModel处理 → 生成新State → UI更新 流程不可逆,确保状态变更可追溯。

  2. 状态更新规则

    • 每次生成全新State对象而非修改现有状态4
    • 通过copy()map()等函数式操作实现不可变性6

三、优势与挑战

优势挑战
状态变化可预测性高15复杂页面易导致状态膨胀6
线程安全(不可变状态)6高频更新可能增加内存开销6
单元测试覆盖率提升5学习曲线较陡峭5

四、扩展实践

  • 事件总线优化‌:使用SharedFlow处理一次性事件(如Toast提示),避免状态残留6
  • 分层设计‌:分离Repository(数据层)、UseCase(业务逻辑层)提升可维护性5
  • Compose适配‌:通过mutableStateOfViewModel无缝集成,实现声明式UI更新2

通过上述设计,MVI架构可有效解决传统架构中状态分散和双向数据绑定带来的维护性问题