Jetpack 架构组件 -> ViewModel

在 Android 开发中,ViewModel 是 Jetpack 架构组件 的核心部分,用于以生命周期感知的方式管理和存储 UI 相关的数据。其主要目的是解决以下痛点:

核心作用

  1. 数据持久化:在配置更改(如屏幕旋转)时保留数据

  2. 生命周期感知:避免内存泄漏,自动清理资源

  3. UI 与数据分离:遵循关注点分离原则(Separation of Concerns)

  4. 数据共享:在 Fragment 之间共享数据

基本使用步骤

1. 添加依赖

在 build.gradle 中添加:

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2" // Kotlin
    // 或 Java 版本
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.6.2"
}
2. 创建 ViewModel 类
class MyViewModel : ViewModel() {
    // 使用 LiveData 存储数据(可观察)
    private val _counter = MutableLiveData(0)
    val counter: LiveData get() = _counter

    fun increment() {
        _counter.value = _counter.value?.plus(1)
    }

    // 当 ViewModel 被销毁时调用
    override fun onCleared() {
        // 清理资源
    }
}
3. 在 Activity/Fragment 中使用
class MainActivity : AppCompatActivity() {
    private lateinit var viewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 获取 ViewModel 实例(系统自动管理生命周期)
        viewModel = ViewModelProvider(this).get(MyViewModel::class.java)

        // 观察数据变化
        viewModel.counter.observe(this) { count ->
            textView.text = "Count: $count"
        }

        button.setOnClickListener {
            viewModel.increment()
        }
    }
}

关键特性详解

1. 生命周期范围
  • ViewModel 的生命周期比 Activity/Fragment 更长

  • 存活范围:从 Activity 的 onCreate() 到完全销毁(onDestroy()

  • 屏幕旋转时不会被销毁

2. 配合 LiveData 使用
  • LiveData:可观察的数据持有者

  • 自动更新 UI(仅当 UI 处于活跃状态时)

  • 避免内存泄漏(自动取消订阅)

3. ViewModelFactory(带参数初始化)
class UserViewModel(private val userId: String) : ViewModel() { ... }

// 创建 Factory
class UserViewModelFactory(private val userId: String) : ViewModelProvider.Factory {
    override fun  create(modelClass: Class): T {
        return UserViewModel(userId) as T
    }
}

// 使用
val factory = UserViewModelFactory("user123")
viewModel = ViewModelProvider(this, factory).get(UserViewModel::class.java)
4. Fragment 间共享数据

// 在 Activity 中获取
val sharedViewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)

// 多个 Fragment 使用同一个实例

最佳实践

  1. 绝不持有 Context
    ❌ 避免存储 Activity/View 引用(可能泄漏)
    ✅ 若需应用上下文,使用 AndroidViewModel(application)

  2. 轻量化职责
    ViewModel 应只处理 UI 数据逻辑,不包含:

    • 视图操作(如显示 Toast)

    • 业务逻辑(应放在 Domain 层)

  3. 结合 Repository 模式


    Jetpack 架构组件 -> ViewModel_第1张图片

  4. 测试友好
    由于不依赖 Android 框架,可直接进行 JUnit 测试:

    @Test
    fun testCounterIncrement() {
        val viewModel = MyViewModel()
        viewModel.increment()
        assertEquals(1, viewModel.counter.value)
    }


常见问题解决方案

问题场景 解决方案
需要保存 Bundle 数据 使用 SavedStateHandle
进程被系统杀死后恢复 结合 onSaveInstanceState()
异步操作回调 使用 LiveData 或 Kotlin 协程
多模块需要相同数据 依赖注入(如 Hilt)

代码示例:SavedStateHandle

class SavedStateViewModel(private val state: SavedStateHandle) : ViewModel() {
    val data: LiveData 
        get() = state.getLiveData("key")

    fun saveData(value: String) {
        state.set("key", value)
    }
}

// 获取实例
ViewModelProvider(this).get(SavedStateViewModel::class.java)

学习资源

  1. 官方文档

  2. Android Codelabs 教程

  3. GitHub 示例

掌握 ViewModel 是构建健壮 Android 应用的基础,它能显著提升代码质量和用户体验!建议结合 LiveDataDataBinding 和 Coroutines 进行综合实践。

你可能感兴趣的:(jetpack,架构,android,jetPack)