1.ViewModel的出现
ViewModel应该是Jetpack中最重要的组件之一了。在以前,Activity要负责逻辑处理,又要控制UI展示,还要处理网络回调,导致大型项目难以维护。于是,ViewModel来帮助Activity分担一部分工作,ViewModel就专门用于存放和界面相关的工作。
2.ViewModel的使用
(1)基本步骤:
- 在app/build.gradel文件添加依赖
dependencies{ ... implementation "androidx.lifecycle:lifecycle-extensions:2.2.0" }
- 创建ViewModel的子类
class MainViewModel:ViewModel(){ var counter=0 }
- 在MainActivity中创建ViewModel的实例
viewModel=ViewModelProvider(this).get(MainViewModel::class.java)
(2)ViewModel的作用
- 手机发生横纵屏旋转的时候,存放在Activity的数据不会丢失。
由图一可以看出ViewModel的生命周期比Activity的生命周期长,所以Activity旋转的时候,ViewModel的数据任然存在。
图一:
下面我们通过普通的计算器来实现这个功能
在界面上添加一个按钮,每点击一次按钮就让计算器加1,并且把最新的计数显示在页面上,运行完成后,不管你怎样翻转,页面的数据不会丢失。
在布局文件中添加按钮和TextView
<TextView android:id="@+id/infoText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:textSize="32sp" /> <Button android:id="@+id/plusOneBtn" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="Plus One"/>
创建ViewModel的子类
class MainViewModel: ViewModel() { var counter=0 }
在MainActivity中调用ViewModel的实例,每点击一次按钮就让计算器加1。
class MainActivity : AppCompatActivity() { lateinit var viewModel: MainViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewModel=ViewModelProvider(this).get(MainViewModel::class.java) val plusOneBtn:Button=findViewById(R.id.plusOneBtn) plusOneBtn.setOnClickListener { viewModel.counter++ refreshCounter() } refreshCounter() } private fun refreshCounter() { val infoText:TextView=findViewById(R.id.infoText) infoText.text=viewModel.counter.toString() } }
- 退出程序后再打开,页面数据不会丢失。
实现这个功能,我们需要在退出程序的时候对当前这个计数进行保存,然后在重新打开这个程序的时候读取之前保存的计数,并将这个计数作为参数传递给MainViewModel。
创建ViewModel的子类,给MainViewModel的构造函数添加参数
class MainViewModel(countReserved:Int): ViewModel() { var counter=countReserved }
创建ViewModelProvider.Factory的子类,在这个类里面创建ViewModel的实例并且给ViewModel的构造函数赋值。
class MainViewModelFactory(private val countReserved:Int): ViewModelProvider.Factory { override fun <T : ViewModel?> create(modelClass: Class<T>): T { return MainViewModel(countReserved) as T //这个create方法的执行事件和Activity的生命周期无关,所以可以直接使用MainViewModel来创建实例 } }
退出程序的时候对当前这个计数进行保存,然后在重新打开这个程序的时候读取之前保存的计数,并将这个计数作为参数传递给MainViewModel,每点击一次按钮就让计算器加1,并且把最新的计数显示在页面上。
class MainActivity : AppCompatActivity() { lateinit var viewModel: MainViewModel lateinit var sp:SharedPreferences override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val countReserved=sp.getInt("count_reserved",0) viewModel=ViewModelProvider(this,MainViewModelFactory(countReserved)).get(MainViewModel::class.java) sp=getSharedPreferences("data",Context.MODE_PRIVATE) val plusOneBtn:Button=findViewById(R.id.plusOneBtn) plusOneBtn.setOnClickListener { viewModel.counter++ refreshCounter() } refreshCounter() } override fun onPause() { super.onPause() sp.edit().putInt("count_reserved",viewModel.counter) } private fun refreshCounter() { val infoText:TextView=findViewById(R.id.infoText) infoText.text=viewModel.counter.toString() } }