Android 架构模式(MVC / MVP / MVVM / MVI)
Android 架构演进
1. MVC
Model ← Controller → View
↑ ↓
└───────────────┘
- Android 中 Activity 既是 Controller 又是 View,导致职责混乱
- 随业务增长 Activity 代码膨胀,难以测试
2. MVP
View (Activity/Fragment)
↕ 接口
Presenter (业务逻辑)
↕
Model (数据层)
- View 和 Presenter 通过接口解耦,便于单元测试
- 缺点:接口类爆炸,Presenter 持有 View 引用需注意内存泄漏
3. MVVM(Google 官方推荐)
View (Activity/Fragment)
↓ 观察
ViewModel (持有 LiveData/StateFlow)
↕
Repository
↕
Remote DataSource / Local DataSource
ViewModel 核心优势
- 生命周期感知:屏幕旋转不丢失数据
- 不持有 View 引用,无内存泄漏风险
SavedStateHandle:进程被杀后恢复状态
class UserViewModel(private val repo: UserRepository) : ViewModel() {
private val _uiState = MutableStateFlow(UiState())
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
fun loadUser(id: String) {
viewModelScope.launch {
_uiState.update { it.copy(loading = true) }
val user = repo.getUser(id)
_uiState.update { it.copy(user = user, loading = false) }
}
}
}
4. MVI(单向数据流)
User Action (Intent)
↓
ViewModel 处理 → 新 State
↓
View 渲染
- State:UI 的完整快照,单一数据源
- Intent:用户操作,密封类描述所有可能事件
- 单向数据流:状态不可变,每次更新生成新 State
- 优点:状态可预测、易于调试和测试
- 代表库:Orbit MVI、MVI Kotlin
sealed class UserIntent {
data class LoadUser(val id: String) : UserIntent()
object Logout : UserIntent()
}
data class UserState(
val user: User? = null,
val loading: Boolean = false,
val error: String? = null
)
5. Clean Architecture 分层
Presentation Layer (ViewModel + UI)
↓
Domain Layer (UseCase + Entity) ← 纯 Kotlin,无 Android 依赖
↓
Data Layer (Repository + DataSource)
- UseCase(交互器):封装单一业务规则,可单独测试
- Repository:抽象数据来源,协调本地缓存和远端数据
- 依赖规则:内层不依赖外层
6. Hilt 依赖注入
@HiltAndroidApp class App : Application()
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
@Inject lateinit var viewModel: UserViewModel
}
@Module @InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides @Singleton
fun provideRetrofit(): Retrofit = Retrofit.Builder()...
}
7. 高频面试题
- ViewModel 为什么能在屏幕旋转后存活? 存储在
ViewModelStore中,与 Activity 生命周期解绑 - LiveData 和 StateFlow 如何选择? 新项目推荐 StateFlow(更强大,支持初始值,协程原生)
- Repository 的作用? 单一数据源,屏蔽本地/远端差异,统一数据格式
- UseCase 一定需要吗? 简单场景可省略,复杂业务规则建议抽取便于测试