ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。
ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。
简单的说就是,在android中,当Activity重建或销毁时,页面上的数据会丢失。为了保存页面的数据,我们以前通常的做法是在 onSaveInstanceState 中,将数据保存到 bundle 中,再在 onCreate 中将 bundle 中的数据取出来。
而使用 ViewModel,我们就无需再用这种方法保存,因为 ViewModel 会自动感知生命周期,处理数据的保存与恢复。即数据可在发生屏幕旋转等配置(其它例如分辨率调整、权限变更、系统字体样式、语言变更等)更改后继续留存。
ViewModel也属于 androidx.lifecycle 包; 导入方式和Lifecycle类似。
dependencies {
def lifecycle_version = "2.2.0"
def arch_version = "2.1.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
}
完整的架构组件导入方式请参看:
https://developer.android.google.cn/jetpack/androidx/releases/lifecycle#declaring_dependencies
例如,如果您需要在应用中显示用户列表,请确保将获取和保留该用户列表的责任分配给 ViewModel,而不是 Activity 或 Fragment,如以下示例代码所示:
class MyViewModel : ViewModel() {
//延迟
private val users: MutableLiveData<List<User>> by lazy {
MutableLiveData().also {
loadUsers()
}
}
fun getUsers(): LiveData<List<User>> {
return users
}
// 异步
private fun loadUsers() {
// Do an asynchronous operation to fetch users.
}
}
然后,可以从 Activity 访问该列表,如下所示:
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val model: MyViewModel by viewModels()
model.getUsers().observe(this, Observer<List<User>>{ users ->
// update UI
})
}
}
ViewModel 对象存在的时间比视图或 LifecycleOwners 的特定实例存在的时间更长。
ViewModel 对象可以包含 LifecycleObservers,如 LiveData 对象。但是,ViewModel 对象绝不能观察对生命周期感知型可观察对象(如 LiveData 对象)的更改。
通常在系统首次调用 Activity 对象的 onCreate() 方法时请求 ViewModel。
假设您有一个 Fragment,在该 Fragment 中,用户从列表中选择一项,还有另一个 Fragment,用于显示选定项的内容。
传统的处理方式是这两个 Fragment 都需要定义某种接口描述,并且所有者 Activity 必须将两者绑定在一起。
可以使用 ViewModel 对象解决这一常见的难点。这两个 Fragment 可以使用其 Activity 范围共享 ViewModel 来处理此类通信,如以下示例代码所示:
//Activity 不需要执行任何操作,也不需要对此通信有任何了解。
//除了 SharedViewModel 约定之外,Fragment 不需要相互了解。
//每个 Fragment 都有自己的生命周期,而不受另一个 Fragment 的生命周期的影响。
class SharedViewModel : ViewModel() {
val selected = MutableLiveData<Item>()
fun select(item: Item) {
selected.value = item
}
}
class MasterFragment : Fragment() {
private lateinit var itemSelector: Selector
private val model: SharedViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
itemSelector.setOnClickListener { item ->
// Update the UI
}
}
}
class DetailFragment : Fragment() {
private val model: SharedViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.selected.observe(viewLifecycleOwner, Observer<Item> { item ->
// Update the UI
})
}
}
先看实现效果:点击按钮,数字 ++

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.528"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.313" />
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/plusbtn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.547"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv" />
</androidx.constraintlayout.widget.ConstraintLayout>
class NumberPlusViewModel: ViewModel() {
var number = 0
}
class MainActivity : AppCompatActivity() {
private val numberPlusViewModel by viewModels<NumberPlusViewModel>();
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tv.text = numberPlusViewModel.number.toString()
btn1.setOnClickListener {
numberPlusViewModel.number++
tv.text = numberPlusViewModel.number.toString()
}
}
}
注意上述代码中的 viewModels 扩展函数,来源于 "androidx.activity:activity-ktx:1.1.0" ,记得添加依赖
dependencies {
implementation "androidx.activity:activity-ktx:1.1.0"
}
// 即:
//Lazy<VM> ComponentActivity.viewModels(noinline factoryProducer: () -> ViewModelProvider.Factory = null)
//返回一个延迟委托以访问 ComponentActivity 的 ViewModel。如果已指定 factoryProducer,则它返回的 ViewModelProvider.Factory 将用于首次创建 ViewModel。
如果运行代码,还是报错,记得配置 compileOptions。
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}






















