为什么要用架构?
没有良好架构的 Android 应用,业务逻辑往往散布在 Activity/Fragment 中,导致这些类变成数千行的”上帝类”,难以测试和维护。MVVM 是 Google 官方推荐的架构模式,配合 Architecture Components 可以大幅提升代码质量。
MVVM 三层结构
- Model:数据层,负责从网络、数据库等数据源获取数据。通常包含 Repository 模式。
- View:UI 层,由 Activity/Fragment/Composable 组成,负责展示数据和接收用户输入。
- ViewModel:持有 UI 状态,处理业务逻辑,作为 View 和 Model 之间的桥梁。
实战代码
Model 层
data class User(val id: Int, val name: String, val avatar: String)
class UserRepository {
private val api = RetrofitClient.userApi
private val dao = AppDatabase.instance.userDao()
suspend fun getUser(id: Int): User {
// 先返回缓存,再请求网络
val cached = dao.getUser(id)
return try {
val remote = api.getUser(id)
dao.insertUser(remote)
remote
} catch (e: Exception) {
cached ?: throw e
}
}
}
ViewModel 层
class UserViewModel(
private val repository: UserRepository
) : ViewModel() {
private val _uiState = MutableStateFlow(UserUiState())
val uiState: StateFlow = _uiState.asStateFlow()
fun loadUser(id: Int) {
viewModelScope.launch {
_uiState.update { it.copy(isLoading = true) }
try {
val user = repository.getUser(id)
_uiState.update { it.copy(user = user, isLoading = false) }
} catch (e: Exception) {
_uiState.update { it.copy(error = e.message, isLoading = false) }
}
}
}
}
data class UserUiState(
val user: User? = null,
val isLoading: Boolean = false,
val error: String? = null
)
View 层
@AndroidEntryPoint
class UserFragment : Fragment() {
private val viewModel: UserViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.uiState
.flowWithLifecycle(viewLifecycleOwner.lifecycle)
.onEach { state -> render(state) }
.launchIn(viewLifecycleOwner.lifecycleScope)
viewModel.loadUser(1)
}
private fun render(state: UserUiState) {
binding.progressBar.isVisible = state.isLoading
state.user?.let { binding.nameText.text = it.name }
state.error?.let { showToast(it) }
}
}
核心原则
- 单一数据源:每种数据类型只有一个可信来源(通常是 Repository)。
- 单向数据流 (UDF):数据从 ViewModel 流向 View,事件从 View 流向 ViewModel。
- ViewModel 不持有 View 引用:避免内存泄漏,使用 StateFlow/LiveData 通信。
- 依赖注入:使用 Hilt/Koin 管理依赖,方便测试。
推荐技术栈
- 网络:Retrofit + OkHttp + Kotlin Coroutines
- 数据库:Room
- DI:Hilt(基于 Dagger)
- 状态:StateFlow / LiveData
- 测试:JUnit + MockK + Turbine