Android dataBinding入门| 青训营笔记

199 阅读2分钟

DataBinding

这是我参与「第四届青训营 」笔记创作活动的第1天

在Android实现MVVM架构, 那么DataBinding是很好的选择

  • findviewById只是他的一小部分内容,如果只是替换findviewById官方推荐用viewBinding
  • ViewModel属于DataBinding自动生成的类
android {
        ...
        dataBinding {
            enabled = true
        }
    }
    

1:XML布局详解

基本的布局结构如下所示

<layout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
            <variable
                name="viewmodel"
                type="com.myapp.data.ViewModel" />
        </data>
        <ConstraintLayout... /> <!-- UI layout's root element -->
    </layout>
    
  • 布局根节点必须是 ,同时layout只能包含一个view标签

  • 标签来指定类

    • <variable
          name="user"<!--类对象-->
        type="com.yxl.databing.UserBean" />
      

      type需要指定具体的数据类的包名

    • 或者像导包一样

    • <import type="com.yxl.databing.UserBean" />
      <variable
          name="user"
          type="UserBean" />
      ​
      
  • allas 可以在两个类名相同(不同的包下的相同类名)的时候 重命名来加以区分

    • <import type="com.yxl.databing.UserBean" alias="MyUserBean"/>
      <variable
          name="user"
          type="MyUserBean" />
      
  • include

    • 在一个layout被include的时候,可能需要传递变量的值
    • <include
       layout="@layout/include_view"
       bind:userName="@{user}"/>
      

2:获取binding类的方式

activity中使用

  1. 方式一
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

2.方式二

ActivityMainBinding activityMainBinding1=ActivityMainBinding.inflate(getLayoutInflater());

此方法与viewBinding 获取的方法类似

FragmentListViewRecyclerView 适配器中使用数据绑定项

    ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
    // or
    ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

然后绑定数据

activityMainBinding.setUser(user);

3:属性使用

自己bean类的属性

android:text="@{user.lastName}"

除了使用自己定义的类的属性,还可以使用其他控件的数据

通过id(驼峰命名法转化)引用

<EditText
        android:id="@+id/example_text"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"/>
    <TextView
        android:id="@+id/example_output"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{exampleText.text}"/>
    

image-20220727121825919

如图所示可以根据edittext实时改变textview

<运算符需要转义为 &lt

由于<在在xml语言中的特殊性在运算时需要转义

android:text="@{user.age&lt;5? @string/app_name :  @string/kkk}"
  • 使用字面字符串

    image-20220727125238057

  • 资源文件用@ 来引用

  • null 合并运算符:

    null 合并运算符(??)左边不为 null 或正确,则返回左边,否则返回右边

避免出现 Null 指针异常

生成的数据绑定代码会自动检查有没有 null 值并避免出现 Null 指针异常。例如,在表达式 @{user.name} 中,如果 user 为 Null,则为 user.name 分配默认值 null。如果您引用 user.age,其中 age 的类型为 int,则数据绑定使用默认值 0

关于defalut

android:text="@{user.lastName,default=myName}"

default只是在开发时可以在preview界面有一个预览效果,在实际运行之后不会显示

4:可观察的数据类

在数据改变之后通知ui来更新

1:BaseObservable

package com.yxl.roomdatabase;
​
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
​
/**
 * @author yinxiaolong
 * @describe
 * @data: 
 */
public class MyBean extends BaseObservable {
​
    String name;
    String age;
​
    @Bindable
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }
​
    @Bindable//如果属性时public直接在属性前加注解就可以
    public String getAge() {
        return age;
    }
​
    public void setAge(String age) {
        this.age = age;
        notifyPropertyChanged(BR.age);//通知改变
    }
}

2:observableField

Java 编程语言创建 public final 属性,或在 Kotlin 中创建只读属性,

    private static class User {
        public final ObservableField<String> firstName = new ObservableField<>();
        public final ObservableField<String> lastName = new ObservableField<>();
        public final ObservableInt age = new ObservableInt();
    }

如需访问字段值,请使用 set()get() 访问器方法

在activity中更新数据

MyObservableFildeBean myObservableFildeBean=new MyObservableFildeBean();
activityMainBinding.setMyObserableBean(myObservableFildeBean);
myObservableFildeBean.age.set(18);
myObservableFildeBean.firstName.set("firstName");
myObservableFildeBean.lastname.set("lastname");
  • observableArrayMap 容器类使用

    xml中

    <data>
        <import type="androidx.databinding.ObservableMap"/>
        <variable
            name="obserableMap"
            type="ObservableMap&lt;String,Object>" />
    </data>
    .....
     android:text="@{String.valueOf(obserableMap.google)}"
    

    activity中

    ObservableMap<String , Object> objectObservableMap=new ObservableArrayMap<>();
        activityMainBinding.setObserableMap(objectObservableMap);
        objectObservableMap.put("google",100);
        objectObservableMap.put("vivo",78);

此外还有ObservableArrayList

5:双向绑定数据

前面是model改变后view自动动态跟新

也支持view改变使model改变

主要就是将原来的 @{....} 表达式改变为 @={...}

此时需要注意是否会出现无限循环的问题,在数据不变时就不进行更新

   
    public class LoginViewModel extends BaseObservable {
        // private Model data = ...

         @Bindable
        public Boolean getRememberMe() {
            return data.rememberMe;
        }

        public void setRememberMe(Boolean value) {
            // Avoids infinite loops.
            if (data.rememberMe != value) {
                data.rememberMe = value;

                // React to the change.
                saveData();

                // Notify observers of a new value.
                notifyPropertyChanged(BR.remember_me);
            }
        }
    }

参考自官方文档