自学jetpack的ViewModel、LiveData、DataBinding这三个东东之后,照着教程做了一遍,记录一下思路与总结:
先po一下教学视频链接,讲的真的是太好了,好看得我都快哭了,强烈推荐
https://www.bilibili.com/video/av50954019?p=10
https://www.bilibili.com/video/av50954019?p=11
https://www.bilibili.com/video/av50954019?p=12
https://www.bilibili.com/video/av50954019?p=13
我要实现的是通过DataBinding和ViewModel实现一个类似计分器的东西,积分器里有两列,点击每一列数字下面的按钮,数字即可加上响应的数字,同时数字不会被旋转屏销毁。
首先是实现步骤:
1.创建项目,并在build.gradle中添加响应的设置与依赖:
1.1在build.gradle的defaulConfig中添加dataBinding
dataBinding{
enabled true
}
1.2在依赖中添加lifecycle包
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
2.创建一个Score类,同时继承于ViewModel。接着使用 MutableLiveData和泛型来定义属性。
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class Score extends ViewModel {
MutableLiveData<Integer> a;
MutableLiveData<Integer> b;
public MutableLiveData<Integer> getA() {
if( a == null ){
a = new MutableLiveData<>();
a.setValue(0);
}
return a;
}
public MutableLiveData<Integer> getB() {
if(b == null){
b = new MutableLiveData<>();
b.setValue(0);
}
return b;
}
public void addA(int p){
a.setValue( a.getValue() + p );
}
public void addB(int p){
b.setValue( b.getValue() + p );
}
}
3.对acticity_main.xml文件进行修改,方法是点击文件第一或者第二行的黄色小灯泡,点击Conver to data bindiing layout,xml文件会做少量改变并出现一个data标签:
解释一下,data中的variable标签有两个属性,一个是name,一个是type,其中type属性填写的是你要在xml文件中使用的类,name属性是一个你随便怎么填写的字符串,用来定义type这个类,就好像在xml文件中实例化Score类,所以这段标签就等于在xml文件中Score score = new Score();这样做之后就可以在xml文件中填写java代码了。
4.在MainActivity.java中填写并绑定相应的信息
public class MainActivity extends AppCompatActivity {
//定义Score对象
Score score;
//ActivityMainBinding binding;是自动生成的,照着填写就行
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//使用binding绑定activity_main.XML文件,绑定之后即可调用XML文件中的所有标签
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
//setContentView(R.layout.activity_main);
//将score绑定到ViewModel
score = new ViewModelProvider(this).get(Score.class);
//使用binding将java的score对象绑定到刚刚xml文件中data标签中填写的score
//注意这个setScore()也是自动生成的,如果在data中填的name是aaa,那边它生成的是setAaa()
binding.setScore(score);
binding.setLifecycleOwner(this);
}
}
5.到这一步就可以在xml中写入相关的操作,就好像html的DOM操作和jsp中的EL表达式一样
下面是我的例子:
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="0"
android:text="@{String.valueOf(score.getA())}" //代码填写在@{}中
android:textSize="36sp"
app:layout_constraintBottom_toTopOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
//下面是函数的使用
<com.google.android.material.button.MaterialButton
android:id="@+id/btna2"
android:layout_width="130dp"
android:layout_height="45dp"
android:text="+2"
android:onClick="@{()->score.addA(2)}" //需要在()->后接函数,这有点像C中的指针
android:textColor="@android:color/white"
android:theme="@style/Theme.MaterialComponents"
app:backgroundTint="@color/design_default_color_secondary"
app:cornerRadius="20dp"
app:layout_constraintBottom_toTopOf="@+id/guideline4"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline3" />
因为我们使用了LiveData,它能通过感知数据的变化来达到view的变化,当数据发生变化时我们的Textview也随之变化,这样就不用写什么监听函数和改变view的函数,是不是非常的方便。
个人总结:
ViewModel使前端数据得到保存
LiveData实现了通过底层的数据变化来让表现这个数据的View也随之变化,就是我这个数据变了,和我有关的View也跟着变了。
DataBinding简化了通过ViewModel和LiveData的实现感知数据变化的操作,同时实现了xml中的标签和java代码的互通。