参考:
计分器(ViewModel、Databinding实现数据的保存和控件操作)
通过视图绑定功能,您可以更轻松地编写可与视图交互的代码。
在模块中启用视图绑定之后,系统会为该模块中的每个 XML 布局文件生成一个绑定类。
绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。在大多数情况下,视图绑定会替代 findViewById
。
android {
buildFeatures {
viewBinding true
}
}
为某个模块启用视图绑定功能后,系统会为该模块中包含的每个 XML 布局文件生成一个绑定类。
每个绑定类均包含对根视图以及具有 ID 的所有视图的引用。
系统会通过以下方式生成绑定类的名称:将 XML 文件的名称转换为驼峰式大小写,并在末尾添加“Binding”一词。
public class MyActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_my);
ActivityMyBinding myBinding = ActivityMyBinding.inflate(getLayoutInflater());
setContentView(myBinding.getRoot());
myBinding.textView3.setText("Hello World");
}
}
使用viewBinding比传统findViewById的好处:
1.类型安全:不用担心出现类型转换的错误
2.写法方便,不用写很多声明的代码,使得Activity里面的代码更加整洁
可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。
是实现 view 和 data 绑定的工具,把数据映射到 view 的 xml中,可以在 xml 布局文件中实现 view 的赋值,方法调用。
使用 DataBinding 后,我们不用再写 findViewById,不用再获取控件对象,不用再设置监听,可以节省我们 activity 中的很多获取控件,赋值,添加监听所需要的代码。
android {
buildFeatures {
dataBinding true
}
}
选中布局文件的第一行,按alter+enter就会弹出提示,默认选中data binding layout
<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="data"
type="com.xq.mybottomnavigation.MyViewModel" />
data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MyActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.06" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.15" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.33" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.57326734" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.71049595" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.8535179" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.4475202" />
<TextView
android:id="@+id/textView"
android:layout_width="83dp"
android:layout_height="32dp"
android:text="TeamA"
android:textAlignment="center"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/guideline2"
app:layout_constraintEnd_toStartOf="@+id/guideline8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline" />
<TextView
android:id="@+id/textView2"
android:layout_width="83dp"
android:layout_height="32dp"
android:text="TeamB"
android:textAlignment="center"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/guideline2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline8"
app:layout_constraintTop_toTopOf="@+id/guideline" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
<TextView
android:id="@+id/textView3"
android:layout_width="140dp"
android:layout_height="107dp"
android:text="@{String.valueOf(data.getATeamScore())}"
android:textAlignment="center"
android:textColor="#F30606"
app:layout_constraintBottom_toTopOf="@+id/guideline3"
app:layout_constraintEnd_toStartOf="@+id/guideline11"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline2"
app:layout_constraintVertical_bias="0.682"
tools:text="120" />
<TextView
android:id="@+id/textView4"
android:layout_width="138dp"
android:layout_height="100dp"
android:text="@{String.valueOf(data.getBTeamScore())}"
android:textAlignment="center"
android:textColor="#0CD681"
app:layout_constraintBottom_toTopOf="@+id/guideline3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline12"
app:layout_constraintTop_toTopOf="@+id/guideline2"
app:layout_constraintVertical_bias="0.666"
tools:text="0" />
<Button
android:id="@+id/button2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#8BC34A"
android:onClick="@{()->data.bTeamAdd(1)}"
android:text="+1"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toTopOf="@+id/guideline4"
app:layout_constraintEnd_toStartOf="@+id/guideline10"
app:layout_constraintStart_toStartOf="@+id/guideline12"
app:layout_constraintTop_toTopOf="@+id/guideline3"
app:layout_constraintVertical_bias="0.407" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.05" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.96" />
<Button
android:id="@+id/button3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="#F44336"
android:onClick="@{()->data.aTeamAdd(2)}"
android:text="+2"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toTopOf="@+id/guideline5"
app:layout_constraintEnd_toStartOf="@+id/guideline11"
app:layout_constraintStart_toStartOf="@+id/guideline9"
app:layout_constraintTop_toTopOf="@+id/guideline4"
app:layout_constraintVertical_bias="0.268" />
<Button
android:id="@+id/button4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#8BC34A"
android:onClick="@{()->data.bTeamAdd(2)}"
android:text="+2"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toTopOf="@+id/guideline5"
app:layout_constraintEnd_toStartOf="@+id/guideline10"
app:layout_constraintStart_toStartOf="@+id/guideline12"
app:layout_constraintTop_toTopOf="@+id/guideline4" />
<Button
android:id="@+id/button5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#F44336"
android:onClick="@{()->data.aTeamAdd(3)}"
android:text="+3"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toTopOf="@+id/guideline6"
app:layout_constraintEnd_toStartOf="@+id/guideline11"
app:layout_constraintStart_toStartOf="@+id/guideline9"
app:layout_constraintTop_toTopOf="@+id/guideline5" />
<Button
android:id="@+id/button6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#8BC34A"
android:onClick="@{()->data.bTeamAdd(3)}"
android:text="+3"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toTopOf="@+id/guideline6"
app:layout_constraintEnd_toStartOf="@+id/guideline10"
app:layout_constraintStart_toStartOf="@+id/guideline12"
app:layout_constraintTop_toTopOf="@+id/guideline5"
app:layout_constraintVertical_bias="0.507" />
<Button
android:id="@+id/imageButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="重置"
android:onClick="@{()->data.reset()}"
app:layout_constraintBottom_toTopOf="@+id/guideline7"
app:layout_constraintEnd_toStartOf="@+id/guideline10"
app:layout_constraintStart_toStartOf="@+id/guideline12"
app:layout_constraintTop_toTopOf="@+id/guideline6" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.45373666" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.55" />
<Button
android:id="@+id/button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#F44336"
android:onClick="@{()->data.aTeamAdd(1)}"
android:text="+1"
android:textColor="#FFFFFF"
app:layout_constraintBottom_toTopOf="@+id/guideline4"
app:layout_constraintEnd_toStartOf="@+id/guideline11"
app:layout_constraintStart_toStartOf="@+id/guideline9"
app:layout_constraintTop_toTopOf="@+id/guideline3" />
<Button
android:id="@+id/imageButton3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{()->data.withdraw()}"
android:text="撤销"
app:layout_constraintBottom_toTopOf="@+id/guideline7"
app:layout_constraintEnd_toStartOf="@+id/guideline11"
app:layout_constraintStart_toStartOf="@+id/guideline9"
app:layout_constraintTop_toTopOf="@+id/guideline6" />
androidx.constraintlayout.widget.ConstraintLayout>
layout>
属性绑定:data/variable 中的 data 变量描述了可在此布局中使用的属性。
<data>
<variable
name="data"
type="com.xq.mybottomnavigation.MyViewModel" />
data>
布局中的表达式使用“@{}
”语法写入特性属性中。在这里,TextView 文本被设置为 data 变量的 相关 属性。
定义了会生成对应的getter与setter方法,可在java代码中直接使用。
package com.xq.mybottomnavigation;
import android.util.Log;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class MyViewModel extends ViewModel {
private static final String TAG = MyViewModel.class.getSimpleName();
private MutableLiveData<Integer> ATeamScore;
private MutableLiveData<Integer> BTeamScore;
private int aBack, bBack; //作为存储上一步操作的比分值,用于撤销函数实现
//作为dadabinding中TextView(TeamA)的绑定
public MutableLiveData<Integer> getATeamScore() {
if (ATeamScore == null) {
ATeamScore = new MutableLiveData<>();
ATeamScore.setValue(0);
}
return ATeamScore;
}
//作为dadabinding中TextView(TeamB)的绑定
public MutableLiveData<Integer> getBTeamScore() {
if (BTeamScore == null) {
BTeamScore = new MutableLiveData<>();
BTeamScore.setValue(0);
}
return BTeamScore;
}
public void aTeamAdd(int p) {
aBack = ATeamScore.getValue();
bBack = BTeamScore.getValue();
ATeamScore.setValue(ATeamScore.getValue() + p);
//aTeam的加分控件函数,会绑定到按键的xml文件中的Onclick对应函数上
}
public void bTeamAdd(int p) {
aBack = ATeamScore.getValue();
bBack = BTeamScore.getValue();
BTeamScore.setValue(BTeamScore.getValue() + p);
//bTeam的加分控件函数,会绑定到按键的xml文件中的Onclick对应函数上
}
public void reset()//复位函数,将比分全清零
{
aBack = ATeamScore.getValue();
bBack = BTeamScore.getValue();
ATeamScore.setValue(0);
BTeamScore.setValue(0);
Log.d(TAG, "reset: ");//测试函数是否调用
}
public void withdraw()//撤销函数,返回上一步的比分值
{
Log.d(TAG, "withdraw: ");//测试函数是否调用
ATeamScore.setValue(aBack);
BTeamScore.setValue(bBack);
}
}
public class MyActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_my);
ActivityMyBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_my);
MyViewModel myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
binding.setData(myViewModel);
binding.setLifecycleOwner(this);//这个一定不能少
}
}