一. 故事背景:
假设有这么一个UI,任务是点击按钮然后让N
的值加1
二. 具体操作
① Databinding
- 先来看
XML
文件,你得先会将这个布局转成databinding layout
,只看有注释的地方就行了。
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<variable
name="viewModel" //将这个布局和一个viewModel绑定到一起
type="XXXXXXXXXX.MyViewModel" />//这个类型XXXXX是包名
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/primaryLightColor"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="160dp"
android:layout_marginEnd="163dp"
android:layout_marginBottom="317dp"
android:text="按我让N的值增加1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="176dp"
android:layout_marginTop="280dp"
android:layout_marginEnd="176dp"
android:layout_marginBottom="67dp"
<!---android:text="我是N的值"-->
android:text="@{Integer.toString(viewModel.N)}" //由于是整数,要转换一下
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
② ViewModel
- 功能作用:提供给UI数据,和处理反馈数据,和Repository交互
如图,UI从ViewModel
里获取数据来显示,ViewModel
的数据来自Repository
,在这里呢就是UI中的TextView
要显示的数据就是N
https://codelabs.developers.google.com/codelabs/android-room-with-a-view-kotlin/#0.
- 写
ViewModel
的代码,UI只需要一个N
,那么就设计一个N
class MyViewModel(
//要从Repository取数据的话就加上这个参数
/*private val myRepository: MyRepository*/
): ViewModel(){
var n = MutableLiveData(0)//不直接用LiveData,因为LiveData的value是被保护的 protected
val N: LiveData<Int> = n //这里就完成了给UI提供数据的功能
fun plusN(){ //这里就完成了处理数据的功能
n.value = (n.value?:0) + 1
}
fun XXXX(){
XXXXXXXXXXX//这里就完成了和Repository交互的功能
}
}
- 获取
ViewModel
class MainActivity : AppCompatActivity(){
private lateinit var appBarConfiguration : AppBarConfiguration
private lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/*
此处略去数据绑定的环节,和设置layout的环节
*/
/*
Arg1:application: Application
Arg2:ViewModelStoreOwner
*/
viewModel = ViewModelProvider(applicationContext, this).get(MyViewModel::class.java)
}
ViewModel商店
当然就是现在的MainActivity
.就是说在当前MainActivity
里调用ViewModelProvider(applicationContext, XXX(MainActivity的引用)).get(MyViewModel::class.java)
获取到的都是一个ViewModel
.下面是官方文档,仔细看看,写的挺好,关于ViewModelProvider
的
https://developer.android.com/reference/androidx/lifecycle/ViewModelProvider?hl=en.
③ LiveData
完成监听
class MainActivity : AppCompatActivity(){
private lateinit var appBarConfiguration : AppBarConfiguration
private lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/*
XXXXXXXXXXXXXXX
*/
/*
XXXXXXXXXXXXXXX
XXXXXXXXXXXXXXX
*/
viewModel = ViewModelProvider(applicationContext, this).get(MyViewModel::class.java)
binding = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(不写了)
//监听button的点击事件
binding.button.setOnClickListener{
//调用viewModel里的数据处理方法
viewModel.plusN()
}
//监视N,当N发生改变时,要更新UI
viewModel.N.observe(this, Observer{
binding.textView.text = Integer.toString(it)//这里的it就是N(l
})
}