ViewModel
是 Android 架构组件之一,用于管理 UI 相关的数据 ,并在 配置更改(如屏幕旋转)时保持数据不丢失 。
🔹 1. 添加 ViewModel 依赖 在 build.gradle.kts
(模块级)中添加:
1 2 3 dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") }
🔹 2. 创建 ViewModel (1)基础 ViewModel 1 2 3 4 5 6 7 8 9 import androidx.lifecycle.ViewModel class CounterViewModel : ViewModel() { var count = 0 // ViewModel 变量(Activity 重建后不会丢失) fun increment() { count++ } }
🔹 3. 在 Activity/Fragment 中使用 (1)Activity 获取 ViewModel 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import android.os.Bundle import android.widget.TextView import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { private val counterViewModel: CounterViewModel by viewModels() // 通过 viewModels() 获取 ViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val textView: TextView = findViewById(R.id.counterText) val button: Button = findViewById(R.id.incrementButton) // 显示当前计数 textView.text = counterViewModel.count.toString() // 点击按钮增加计数 button.setOnClickListener { counterViewModel.increment() textView.text = counterViewModel.count.toString() } } }
✅ 即使旋转屏幕,count
也不会重置 。
🔹 4. ViewModel + LiveData 监听数据变化 使用 LiveData
,UI 会自动更新 :
(1)ViewModel(使用 LiveData
) 1 2 3 4 5 6 7 8 9 10 11 12 import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class CounterViewModel : ViewModel() { private val _count = MutableLiveData(0) // 可变 LiveData val count: LiveData<Int> = _count // 只暴露不可变 LiveData fun increment() { _count.value = (_count.value ?: 0) + 1 // 更新数据 } }
(2)Activity 观察 LiveData 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class MainActivity : AppCompatActivity() { private val counterViewModel: CounterViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val textView: TextView = findViewById(R.id.counterText) val button: Button = findViewById(R.id.incrementButton) // 观察 LiveData,自动更新 UI counterViewModel.count.observe(this) { newCount -> textView.text = newCount.toString() } button.setOnClickListener { counterViewModel.increment() } } }
✅ LiveData
确保数据变化时,UI 会自动更新 。
🔹 5. 处理 ViewModel 依赖(带参数的 ViewModel) (1)ViewModel 需要参数 如果 ViewModel
需要参数(如 Repository
),需要创建 ViewModelProvider.Factory
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class CounterViewModel(private val startValue: Int) : ViewModel() { private val _count = MutableLiveData(startValue) val count: LiveData<Int> = _count fun increment() { _count.value = (_count.value ?: 0) + 1 } } // 自定义 ViewModelFactory class CounterViewModelFactory(private val startValue: Int) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { if (modelClass.isAssignableFrom(CounterViewModel::class.java)) { @Suppress("UNCHECKED_CAST") return CounterViewModel(startValue) as T } throw IllegalArgumentException("Unknown ViewModel class") } }
(2)Activity 获取带参数的 ViewModel 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class MainActivity : AppCompatActivity() { private val counterViewModel: CounterViewModel by viewModels { CounterViewModelFactory(5) // 传入初始值 5 } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val textView: TextView = findViewById(R.id.counterText) val button: Button = findViewById(R.id.incrementButton) counterViewModel.count.observe(this) { newCount -> textView.text = newCount.toString() } button.setOnClickListener { counterViewModel.increment() } } }
✅ 支持带参数的 ViewModel(如从数据库或网络获取初始数据) 。
🔹 6. ViewModel + Room 持久化数据库数据 如果你使用 Room
存储数据,ViewModel
可以直接从 Room
获取 LiveData
:
1 2 3 4 5 6 7 8 9 @Dao interface DiaryDao { @Query("SELECT * FROM diary_entries ORDER BY date DESC") fun getAllDiaries(): LiveData<List<DiaryEntry>> // LiveData 监听数据库 } class DiaryViewModel(private val diaryDao: DiaryDao) : ViewModel() { val diaryList: LiveData<List<DiaryEntry>> = diaryDao.getAllDiaries() }
在 Fragment
观察数据:
1 2 3 diaryViewModel.diaryList.observe(viewLifecycleOwner) { diaryList -> diaryAdapter.submitList(diaryList) // 更新 UI }
✅ Room + ViewModel + LiveData 确保数据持久化,并自动更新 UI 。
🔹 7. ViewModel + Kotlin Flow(协程) 如果你用 Flow
,可以这样:
1 2 3 4 class DiaryViewModel(private val diaryDao: DiaryDao) : ViewModel() { val diaryListFlow = diaryDao.getAllDiariesFlow() .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) // 转为 StateFlow }
在 Fragment
中 collect
数据:
1 2 3 4 5 lifecycleScope.launch { viewModel.diaryListFlow.collect { diaryList -> diaryAdapter.submitList(diaryList) } }
✅ Flow
更适合复杂数据流(如数据库、网络请求) 。
🔹 8. ViewModel 生命周期
场景
ViewModel 作用
旋转屏幕
保持数据不丢失
App 进后台
ViewModel 可能被销毁(可用 SavedStateHandle
处理)
Fragment 切换
共享 ViewModel
以保留数据
🔹 总结 ✅ ViewModel
用于管理 UI 相关数据,避免因屏幕旋转导致数据丢失 。 ✅ 搭配 LiveData
自动通知 UI 变化 。 ✅ ViewModel
+ Room
可以自动监听数据库变化 。 ✅ ViewModel
+ Flow
适合复杂数据流处理 。 ✅ ViewModelFactory
用于创建带参数的 ViewModel 。