> 技术文档 > Android ViewModel 深度解析:原理、使用与最佳实践_val viewmodel: splashviewmodel = viewmodel ()

Android ViewModel 深度解析:原理、使用与最佳实践_val viewmodel: splashviewmodel = viewmodel ()


一、ViewModel 概述

ViewModel 是 Android Jetpack 架构组件中的重要一员,专门为解决 Activity 和 Fragment 中的 UI 数据管理问题而设计。它的核心目标是:

  1. 管理 UI 相关数据:以生命周期感知的方式保存和管理数据

  2. 解决配置变更问题:在屏幕旋转等配置更改时保留数据

  3. 避免内存泄漏:自动清理资源,防止 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 的集成、更完善的状态保存机制等),值得开发者持续关注和学习。

  1. 职责单一:每个 ViewModel 应只负责一个屏幕或功能模块

  2. 避免引用 Context:ViewModel 不应持有 Activity/Fragment 的引用

  3. 合理使用 LiveData:暴露不可变的 LiveData,内部使用 MutableLiveData

  4. 结合 Repository:数据操作应委托给 Repository 层

  5. 测试友好: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 或完全避免 Context

    2. 数据重复加载

    问题:每次配置变更都重新加载数据
    解决:在 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,开发者可以:

  6. 构建更健壮、更易维护的应用程序

  7. 提高代码的可测试性

  8. 减少内存泄漏的风险

  9. 提供更好的用户体验