天天看点

MVVM中data binding系列(一)

一、gradle配置
android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"
   ...

    buildFeatures{//注意这里 Gradle 5.0之前的版本是dataBinding,5.0之后的版本是buildFeatures
        dataBinding = true
    }
    
           
二、基础使用

1、添加Model实体类

public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

           

2、再写布局文件

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="student"
            type="com.mvvm.model.Student" />

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{student.name}" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
           android:text="@{String.valueOf(student.age)}" />
    </LinearLayout>
</layout>
           

这里有几个注意点

  • 布局文件的顶层标签是layout ,且不需要有其他多余属性(如android:layout_width、android:layout_height)
  • layout 标签下有两部分,一部分是data标签,定义variable变量,name是变量的名称,这个名称是下面布局控件可以直接使用,type是这个变量的类型,也就是全类名。另外一部分是布局标签,注意这里的布局标签,也就是个UI的顶层布局标签,有且应该只有一个。

3、在Activity中将实体类和布局文件进行绑定

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding dataBind = DataBindingUtil.setContentView(this, R.layout.activity_main);
        Student std = new Student("Tom",22);
        dataBind.setStudent(std);
    }
}
           

这里的DataBindingUtil.setContentView(this, R.layout.activity_main)替换了之前的setContentView(R.layout.activity_main),编译器会在ActivityMainBinding 中生成我们在布局文件里面申明variable 变量student的get和set方法,所以我们在这直接可以调用dataBind.setStudent(std)将model对象直接传给布局文件。这里的dataBind 包含了和布局文件的所有关系,程序也会自动个布局文件里面@{student.age}等相关属性赋值。

4.事件处理

事件处理有两种方式

(1)第一种写法

首先要给需要加事件的控件加上id

<TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{student.name}" />
           

然后回到Activity中

dataBind.tvName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG,"name 的点击事件");
            }
});
           

通过dataBind我们可以拿到布局文件里面指定的控件。然后设置点击事件即可。

(2)第二种写法

在布局文件的data节点上添加属性,声明Onclicklistener变量

<variable
            name="Onclicklistener"
            type="android.view.View.OnClickListener" />
           

在需要添事件的控件上引用该属性

<TextView
            android:id="@+id/tv_age"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{Onclicklistener}"
            android:text="@{String.valueOf(student.age)}" />
           

然后在Activity中通过dataBind使用

dataBind.setOnclicklistener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int id = v.getId();
                switch (id){
                    case R.id.tv_age:
                        Log.d(TAG,"age 的点击事件");
                        break;
                    default:
                        break;
                }
            }
        });
           

最后效果

2020-11-22 07:21:44.788 31088-31088/com.mvvm D/MainActivity: name 的点击事件
2020-11-22 07:22:07.050 31088-31088/com.mvvm D/MainActivity: age 的点击事件
           

5、布局属性

(1)import 属性的使用

<data>
        <import type="com.mvvm.bean.Student"/>
        <variable
            name="student"
            type="Student" />
    </data>
           

import 的意义跟在java代码中相同。

如果两个变量的类名相同,则可以用别名(alias)区分

<data>
        <import type="com.mvvm.model.Student"/>
        <import type="com.mvvm.bean.Student" alias="stud"/>
        <variable
            name="student"
            type="Student" />
        <variable
            name="stud"
            type="Student" />
    </data>
           

6.在布局文件中引入基本数据类型

<variable
            name="score"
            type="int" />
           

程序自动导入了java.lang.*包中的所有类,所以基本数据类型无需导包,除了引入基本数据类型,还可以定义List、Map等集合变量

<import type="java.util.ArrayList" />
  <variable
        name="list"
        type="ArrayList&lt;String>" />
           

注意这里的泛型要用转义字符

使用:

<TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{list.get(1)}" />
           

定义Map

<variable
            name="key"
            type="String" />

        <variable
            name="map"
            type="java.util.Map&lt;String,String&gt;" />
           

这里Map中的泛型也需要加转义符

使用Map

<TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{map.get(key)}" />
           

Activity 中的代码

ArrayList<String> list = new ArrayList<>();
        list.add("一");
        list.add("二");
        list.add("三");
        dataBind.setList(list);
        dataBind.setKey("name");
        Map<String,String> map = new HashMap<>();
        map.put("name","小明");
        dataBind.setMap(map);