一、架构模式演进背景

Android应用架构经历了从简单到复杂的演进过程,主要驱动力包括:

  1. 应用复杂度提升

  2. 可维护性要求提高

  3. 测试驱动开发的普及

  4. 响应式编程的兴起

  5. 谷歌官方架构组件的推动

二、MVC架构深度解析

核心结构

  • Model:数据层,负责数据获取和业务逻辑

  • View:布局文件和Activity/Fragment

  • Controller:通常由Activity/Fragment兼任

Android实现特点

  1. 典型实现问题

    • Activity承担过多职责(视图渲染+业务逻辑+用户交互)

    • 业务逻辑与UI高度耦合

    • 单元测试几乎不可能

  2. 数据流向示意图

    用户操作 → Activity → 业务逻辑 → 数据层
    数据变化 → Activity → 更新UI

使用场景

  • 适用场景

    • 小型工具类应用

    • 快速原型开发

    • 演示性质项目

  • 不适用场景

    • 复杂业务逻辑应用

    • 需要高覆盖率单元测试的项目

    • 长期维护的大型项目

三、MVP架构深度解析

核心改进

  • 引入Presenter层解耦View和Model

  • 通过接口定义交互契约

  • 业务逻辑可独立测试

标准实现模式

  1. 组件职责划分

    • View:仅处理UI展示,实现View接口

    • Presenter:处理业务逻辑,持有View弱引用

    • Model:保持数据操作独立性

  2. 代码结构示例

    // 契约接口
    interface LoginContract {
        interface View {
            fun showLoading()
            fun hideLoading()
            fun showError(message: String)
            fun navigateToHome()
        }
        
        interface Presenter {
            fun login(username: String, password: String)
            fun attachView(view: View)
            fun detachView()
        }
    }
    
    // Presenter实现
    class LoginPresenter(
        private val authRepository: AuthRepository
    ) : LoginContract.Presenter {
        
        private var view: LoginContract.View? = null
        
        override fun attachView(view: LoginContract.View) {
            this.view = WeakReference(view).get()
        }
        
        override fun login(username: String, password: String) {
            view?.showLoading()
            authRepository.login(username, password,
                onSuccess = {
                    view?.hideLoading()
                    view?.navigateToHome()
                },
                onError = { e ->
                    view?.hideLoading()
                    view?.showError(e.message)
                }
            )
        }
    }

优势与挑战

优势

  • 视图与业务逻辑解耦

  • Presenter可独立单元测试

  • 代码可维护性提高

  • 适合中等复杂度项目

挑战

  • 接口数量膨胀

  • Presenter可能变得臃肿

  • 需要手动处理生命周期

使用场景

  • 适用场景

    • 中型商业应用

    • 需要较高测试覆盖率的项目

    • 团队协作开发

  • 不适用场景

    • 超大型复杂项目

    • 需要快速迭代的UI原型

四、MVVM架构深度解析

核心革新

  • 引入ViewModel和Data Binding

  • 双向数据绑定

  • 生命周期感知组件

现代实现方案

  1. 组件架构

    • View:Activity/Fragment + Data Binding

    • ViewModel:提供UI数据流,不持有View引用

    • Repository:数据仓库统一管理数据源

  2. 典型代码结构

    // ViewModel
    class UserViewModel(
        private val userRepo: UserRepository
    ) : ViewModel() {
        
        private val _uiState = MutableStateFlow<UserUiState>(UserUiState.Loading)
        val uiState: StateFlow<UserUiState> = _uiState.asStateFlow()
        
        fun loadUser(userId: String) {
            viewModelScope.launch {
                _uiState.value = UserUiState.Loading
                try {
                    val user = userRepo.getUser(userId)
                    _uiState.value = UserUiState.Success(user)
                } catch (e: Exception) {
                    _uiState.value = UserUiState.Error(e.message)
                }
            }
        }
    }
    
    // UI State
    sealed class UserUiState {
        object Loading : UserUiState()
        data class Success(val user: User) : UserUiState()
        data class Error(val message: String?) : UserUiState()
    }

核心优势

  1. 数据绑定

    • 自动UI更新

    • 减少样板代码

  2. 生命周期安全

    • ViewModel自动保存状态

    • LiveData自动取消订阅

  3. 测试便利

    • ViewModel纯逻辑可测试

    • UI测试更简单

使用场景

  • 适用场景

    • 大型复杂应用

    • 数据驱动型UI

    • 需要响应式编程的项目

    • 谷歌架构组件项目

  • 不适用场景

    • 超简单工具应用

    • 需要严格控制渲染性能的场景

五、架构对比与选型指南

对比维度分析

维度 MVC MVP MVVM
耦合度
可测试性 困难 Presenter易测试 ViewModel易测试
代码量 少(初期) 接口导致膨胀 较少(绑定)
学习曲线 简单 中等 较陡峭
维护成本 高(长期)
谷歌支持 官方支持

选型决策树

是否小型工具类项目?
  → 是 → 选择MVC
  → 否 → 是否需要高测试覆盖率?
    → 是 → 选择MVP/MVVM
    → 否 → 项目是否使用Data Binding?
      → 是 → 选择MVVM
      → 否 → 选择MVP

混合架构实践

  1. MVP+MVVM混合

    • Presenter处理复杂业务逻辑

    • ViewModel管理UI状态

  2. Clean Architecture整合

    复制

    下载

    Presentation层: MVVM
    Domain层: 纯业务逻辑
    Data层: Repository模式

六、现代最佳实践

  1. 状态管理

    • 使用StateFlow/SharedFlow替代LiveData

    • 采用密封类定义UI状态

  2. 依赖注入

    • 使用Hilt实现依赖注入

    • ViewModel通过构造函数注入依赖

  3. 分层架构

    // Data层
    class UserRepository @Inject constructor(
        private val api: UserApi,
        private val dao: UserDao
    ) {
        suspend fun getUser(id: String): User {
            // 网络+缓存策略
        }
    }
    
    // Domain层
    class GetUserUseCase @Inject constructor(
        private val repo: UserRepository
    ) {
        suspend operator fun invoke(id: String): User {
            return repo.getUser(id)
        }
    }
    
    // Presentation层
    class UserViewModel @Inject constructor(
        private val getUserUseCase: GetUserUseCase
    ) : ViewModel() {
        // UI状态管理
    }
  4. 响应式UI

    // Activity中观察状态
    lifecycleScope.launch {
        viewModel.uiState.collect { state ->
            when (state) {
                is UserUiState.Loading -> showProgress()
                is UserUiState.Success -> showUser(state.user)
                is UserUiState.Error -> showError(state.message)
            }
        }
    }

选择适合的架构需要综合考虑项目规模、团队技能、维护周期等因素。现代Android开发推荐以MVVM为基础,结合Clean Architecture原则,使用官方架构组件构建健壮的应用架构。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐