Android ViewModel 深度解析:原理、使用与最佳实践_val viewmodel: splashviewmodel = viewmodel ()
一、ViewModel 概述
ViewModel 是 Android Jetpack 架构组件中的重要一员,专门为解决 Activity 和 Fragment 中的 UI 数据管理问题而设计。它的核心目标是:
-
管理 UI 相关数据:以生命周期感知的方式保存和管理数据
-
解决配置变更问题:在屏幕旋转等配置更改时保留数据
-
避免内存泄漏:自动清理资源,防止 Activity/Fragment 引用泄漏
// 基本ViewModel类定义class MyViewModel : ViewModel() { // 数据将在此保存 var counter = 0}
二、ViewModel 生命周期
理解 ViewModel 的生命周期是其正确使用的关键:
-
ViewModel 的生命周期比创建它的 Activity/Fragment 更长
-
在 Activity 完成(finish)时才会清除
-
屏幕旋转等配置变化不会导致重建
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 获取ViewModel实例 val model: MyViewModel by viewModels() }}
三、ViewModel 的基本使用
1. 添加依赖
首先在 build.gradle 中添加依赖:
dependencies { implementation \"androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2\" // 如果使用ViewModel带SavedState implementation \"androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.2\"}
2. 创建 ViewModel 类
class UserViewModel : ViewModel() { private val _users = MutableLiveData<List>() val users: LiveData<List> = _users init { loadUsers() } private fun loadUsers() { // 模拟数据加载 _users.value = listOf(User(\"张三\"), User(\"李四\")) }}
3. 在 Activity/Fragment 中使用
class UserActivity : AppCompatActivity() { private val userViewModel: UserViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_user) userViewModel.users.observe(this) { users -> // 更新UI updateUserList(users) } }}
四、ViewModel 的高级特性
1. ViewModel 带参数
如果需要传递参数给 ViewModel,可以使用 ViewModelProvider.Factory:
class UserViewModel(private val userId: String) : ViewModel() { // ...}class UserViewModelFactory(private val userId: String) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { return UserViewModel(userId) as T }}// 使用val factory = UserViewModelFactory(\"123\")val viewModel = ViewModelProvider(this, factory).get(UserViewModel::class.java)
2. SavedStateHandle
处理进程死亡后恢复数据:
class SavedStateViewModel(private val state: SavedStateHandle) : ViewModel() { val counter: LiveData = state.getLiveData(\"counter\", 0) fun increment() { state[\"counter\"] = (counter.value ?: 0) + 1 }}
3. 在 Fragment 间共享数据
class SharedViewModel : ViewModel() { val selectedItem = MutableLiveData() fun select(item: Item) { selectedItem.value = item }}// FragmentAval model: SharedViewModel by activityViewModels()// FragmentBval model: SharedViewModel by activityViewModels()
五、ViewModel 最佳实践
随着 Jetpack 组件的不断演进,ViewModel 也在持续增强功能(如与 Hilt 的集成、更完善的状态保存机制等),值得开发者持续关注和学习。
-
职责单一:每个 ViewModel 应只负责一个屏幕或功能模块
-
避免引用 Context:ViewModel 不应持有 Activity/Fragment 的引用
-
合理使用 LiveData:暴露不可变的 LiveData,内部使用 MutableLiveData
-
结合 Repository:数据操作应委托给 Repository 层
-
测试友好:ViewModel 应易于单元测试
// 良好结构的ViewModel示例class OrderViewModel( private val orderRepository: OrderRepository, private val savedStateHandle: SavedStateHandle) : ViewModel() { private val _order = MutableLiveData() val order: LiveData = _order private val _loading = MutableLiveData() val loading: LiveData = _loading fun loadOrder(orderId: String) { _loading.value = true viewModelScope.launch { try { _order.value = orderRepository.getOrder(orderId) } catch (e: Exception) { // 处理错误 } finally { _loading.value = false } } }}
六、常见问题与解决方案
1. ViewModel 内存泄漏
问题:在 ViewModel 中持有 Activity/Fragment 引用
解决:使用 Application Context 或完全避免 Context2. 数据重复加载
问题:每次配置变更都重新加载数据
解决:在 ViewModel 中缓存数据class MyViewModel : ViewModel() { private var cachedData: List? = null fun getData(): LiveData<List> { if (cachedData == null) { loadData() } return Transformations.map(_source) { it } }}
3. 测试困难
解决:依赖注入和接口抽象
class MyViewModel( private val dataSource: DataSourceInterface) : ViewModel() { // ...}// 测试时可以传入Mock实现
七、ViewModel 与协程
ViewModel 内置了 viewModelScope,便于协程管理:
class CoroutineViewModel : ViewModel() { fun fetchData() { viewModelScope.launch { try { val data = repository.fetchData() _uiState.value = UiState.Success(data) } catch (e: Exception) { _uiState.value = UiState.Error(e) } } }}
结语
ViewModel 是现代 Android 开发中不可或缺的架构组件,它优雅地解决了 UI 控制器(Activity/Fragment)中数据管理的难题。通过合理使用 ViewModel,开发者可以:
-
构建更健壮、更易维护的应用程序
-
提高代码的可测试性
-
减少内存泄漏的风险
-
提供更好的用户体验