jetpack : ViewBinding 和 DataBinding + viewmodel + livedata 的使用

参考:

计分器(ViewModel、Databinding实现数据的保存和控件操作)

一、ViewBinding:视图绑定

通过视图绑定功能,您可以更轻松地编写可与视图交互的代码。
在模块中启用视图绑定之后,系统会为该模块中的每个 XML 布局文件生成一个绑定类。
绑定类的实例包含对在相应布局中具有 ID 的所有视图的直接引用。在大多数情况下,视图绑定会替代 findViewById

开启ViewBinding :

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里面的代码更加整洁

二、DataBinding:数据绑定库

可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。
是实现 view 和 data 绑定的工具,把数据映射到 view 的 xml中,可以在 xml 布局文件中实现 view 的赋值,方法调用。
使用 DataBinding 后,我们不用再写 findViewById,不用再获取控件对象,不用再设置监听,可以节省我们 activity 中的很多获取控件,赋值,添加监听所需要的代码。

开启databinding :

android {
    buildFeatures {
        dataBinding true
    }
}

修改布局文件 activity_my :

选中布局文件的第一行,按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代码中直接使用。

MyViewModel :

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);
    }
}

MyActivity :

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);//这个一定不能少
    }
}

你可能感兴趣的:(android)