在Kotlin中实现MVVM架构时,ViewModel和LiveData是两个核心组件,它们能有效实现关注点分离和数据驱动UI的特性。以下是详细的实现指南:
一、MVVM组件职责划分
-
Model层
- 数据模型(Data Classes)
- 数据源(Repository):管理本地/远程数据
- 业务逻辑处理
-
ViewModel层
- 持有和管理与UI相关的数据
- 通过LiveData暴露数据状态
- 处理View层的事件响应
- 不持有View引用
-
View层(Activity/Fragment)
- 观察ViewModel的LiveData
- 处理UI渲染和用户交互
- 最小化业务逻辑
二、环境配置(build.gradle)
// AndroidX依赖
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
implementation 'androidx.activity:activity-ktx:1.6.1' // 简化ViewModel获取
三、核心实现步骤
1. 数据模型与Repository
// 数据模型
data class User(val id: Int, val name: String)
// Repository示例
class UserRepository {
private val fakeRemoteData = listOf(User(1, "Alice"), User(2, "Bob"))
suspend fun loadUsers(): List<User> {
// 模拟网络请求
delay(1000)
return fakeRemoteData
}
}
2. ViewModel实现
class UserViewModel(
private val repository: UserRepository
) : ViewModel() {
private val _users = MutableLiveData<List<User>>()
val users: LiveData<List<User>> = _users
private val _loadingState = MutableLiveData<Boolean>()
val loadingState: LiveData<Boolean> = _loadingState
fun fetchUsers() {
viewModelScope.launch {
_loadingState.value = true
try {
val result = repository.loadUsers()
_users.value = result
} catch (e: Exception) {
// 错误处理(可通过LiveData传递错误状态)
} finally {
_loadingState.value = false
}
}
}
}
3. View层实现(Activity/Fragment)
class MainActivity : AppCompatActivity() {
private val viewModel: UserViewModel by viewModels {
UserViewModelFactory(UserRepository())
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupObservers()
viewModel.fetchUsers()
}
private fun setupObservers() {
viewModel.users.observe(this) { users ->
// 更新RecyclerView
adapter.submitList(users)
}
viewModel.loadingState.observe(this) { isLoading ->
progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
}
}
}
// ViewModel工厂(带参数构造时使用)
class UserViewModelFactory(private val repository: UserRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return UserViewModel(repository) as T
}
}
四、高级实践技巧
1. 使用密封类封装状态
sealed class Resource<T>(
val data: T? = null,
val error: Throwable? = null
) {
class Success<T>(data: T) : Resource<T>(data)
class Loading<T>(data: T? = null) : Resource<T>(data)
class Error<T>(throwable: Throwable, data: T? = null) : Resource<T>(data, throwable)
}
// ViewModel中使用:
private val _state = MutableLiveData<Resource<List<User>>>()
val state: LiveData<Resource<List<User>>> = _state
2. 数据绑定集成
<layout>
<data>
<variable
name="viewModel"
type="com.example.UserViewModel"/>
</data>
<TextView
android:text="@{viewModel.user.name}"
android:visibility="@{viewModel.loading ? View.GONE : View.VISIBLE}" />
</layout>
3. 事件处理(避免重复触发)
class SingleLiveEvent<T> : MutableLiveData<T>() {
private val pending = AtomicBoolean(false)
override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
super.observe(owner) { t ->
if (pending.compareAndSet(true, false)) {
observer.onChanged(t)
}
}
}
override fun setValue(value: T) {
pending.set(true)
super.setValue(value)
}
}
五、最佳实践原则
-
单向数据流: View → ViewModel → Model → ViewModel → View
-
生命周期感知:
- 使用
viewLifecycleOwner(在Fragment中) - 避免在非活跃状态更新UI
- 使用
-
测试策略:
- ViewModel:使用JUnit测试业务逻辑
- LiveData:利用
observeForTesting - Repository:Mock数据源测试
-
内存管理:
- 避免在ViewModel中持有Context
- 使用WeakReference处理必要的外部依赖
六、MVVM优势总结
| 特性 | 优势说明 |
|---|---|
| 关注点分离 | UI逻辑与业务逻辑解耦 |
| 生命周期感知 | 自动管理资源释放,避免内存泄漏 |
| 数据持久化 | ViewModel在配置更改后保持数据 |
| 可测试性 | 各组件可独立测试 |
| 响应式编程 | LiveData自动通知UI更新 |
通过合理使用ViewModel和LiveData,可以构建出健壮、可维护且符合现代Android开发规范的应用程序架构。