Bootstrap

DataBinding 使用教程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

DataBinding 使用教程 基础篇

前言

本篇文章用于记录自己根据官方文档学习DataBinding的记录和总结,若对你学习DataBinding 有助记得点赞呦。

一、DataBinding 是什么?

DataBinding 是 Android Jetpack 提供数据绑定库。借助该库,您可以使用声明性格式(而非程序化地)将布局中的界面组件绑定到应用中的数据源。

二、使用步骤

1.在项目中开启

在项目的 bulid.gradle 文件中添加一下代码开启

android {
       ...
        dataBinding {
            enabled = true
        }
    }

2.开始使用

1、先修改布局文件

数据绑定布局文件略有不同,以根标记 layout 开头,后跟 data 元素和 view 根元素。
修改该 xml 布局如下(Androd Studio 有快捷键 一键修改 鼠标点到跟布局 Alt +Enter 选中如图中所示 然后按enter 键)
在这里插入图片描述

2、布局中定义变量和导入引用类

1 、先定义变量 和导入引用类
2 、在根布局文件使用
以下代码展示了布局文件中的基本使用方法:(注释中有说明)

<?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
  // 1、 定义变量 和导入引用类
 //  所有使用的变量和引用类型要放在 <data> 标签下  data标签只能存在一个
//   若没有变量和引用类型 <data>标签下可以什么都不写
//   引用类型:使用 <import   type =包名+.类名 /> 根据需求导入系统的定义类或自己定义的类 
//   定义变量:使用  <variable name="变量名" type="包名+.类名, 基本类型可以直接使用"/>
//   注意:
//  1、支持基本数据类型和自定义类型  比如 String、int、 User(自定义类型)。
//  2、包名首字母要小写 如:com.example 不能 Com.example 
//  3、类名首字母要大写 如:com.example.User 不能 com.example.user
      <data>
      // 导入引用类型
      <import type="android.view.View" />
       <import type="android.text.TextUtils" />
       <import type="com.example.util.StringUtil" />
//    定义变量  定义后 Databinding 会自动生成 get set 方法
        <variable
            name="name"
            type="String"  />
            
        <variable
            name="price"
            type="int" />
            
        <variable
            name="showPrice"
            type="Boolean" />
            
//           使用自定义类型
           <variable 
               name="user"
               type="com.example.User"/>
       </data>

//   2 、在根布局文件使用  语法:  "@{ }" 或 ='@{ }'   "@={ }" 双向绑定一般用于EditText
     <LinearLayout
         android:orientation="vertical"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
         <TextView android:layout_width="wrap_content"
             android:layout_height="wrap_content"
            // 使用变量 
            //  拼接字符串 可以使用 '@{"用户名:" +name }' 
            // 还可以使用xml 定义的字符串 "@{@string/userName+':'+name}"
             android:text="@{name}"/>

            <TextView 
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             //  通过定义的变量 控制 view 显示隐藏
             // 可以使用表达三元表达式
             android:visibility="@{showPrice?View.VISIBLE:View:GONE}"
             // 引用的类型 使用基本类型不用导入包 可以直接使用
             // 还可以直接使用String,"@{String.valueOf(price)}"  或  "@{price+1}"
             android:text="@{StringUtil.intToString(price)}"/>
            
         <TextView android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            //使用 自定类型 : 变量名.属性名(还可以是定义的 get方法名 如 public String getAllName(){},  "@{user.allName}"  )
            android:text="@{user.firstName}"/>
        
         <TextView android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.lastName}"/>
                <EditText 
                 android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               // 双向绑定
              // EditText 中输入与的内容变化会直接更新 User中的 firstName 不需要在使用set方法设置内容 
              android:text="@={user.firstName}"/>
   </LinearLayout>
</layout>   

3、 在Activity 、Fragment、Dialog、PopupWindow、自定义View、includ标签 等使用

  1. Databinging 自动生成的了的命名规则(大驼峰):layout文件名+Binding
    如 @layout/activity_main Databinging会自动生成AcitvityMainBinding类 我们可以直接使用。

  2. 在自定义View中 一定要设置根布局View 的tag(view.setTag(“@laytout/layout文件名+_0”) _0 不能少如: 一定要设置, 一定要设置, 一定要设置,不要问我为啥知 道的 问就是一定要设置。
    因为Databinging在自动生成文件时 会根据设 查找tag查找 在Activity 、Fragment等系统的类中已经帮我们自动设置了(setTag(@layout/activity_main_0))) 所以自定义view中一定要设置。

// 可封装到BaseAcitivty中不用每次都写一遍 extends BaseActivity<ActivityMainBinding >
public MainActivity extends AppCompatActivity{
// 使用BaseAcitivty 可以不用写
ActivityMainBinding binding;
  // 使用BaseAcitivty 可以不用写 onCreate 方法
    @Override
    protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
       binding.setLifecycleOwner(this);
       User user = new User("Test", "User");
       binding.setUser(user);
       binding.setName("张三");
        binding.setPrice(100);
        binding.setShowPrice(false)
    }
   // @Override
  //  protected int getLayoutId() {
//        return R.layout.activity_main;
  //  }

 // @Override
  //  protected void initView() {
    //  User user = new User("Test", "User");
    //   binding.setUser(user);
  //     binding.setName("张三");
//        binding.setPrice(100);
//        binding.setShowPrice(false)
 //   }
 
    // 使用BaseAcitivty 可以不用写
   @Override
    protected void onDestroy() {
        super.onDestroy();
        if (binding != null) {
            binding.unbind();
        }
    }
    
}


    public class User {
      public final String firstName;
      public final String lastName;
      public User(String firstName, String lastName) {
          this.firstName = firstName;
          this.lastName = lastName;
      }
       // 可以设置 也可以不设置
        public voild setFirstName(String firstName ) {
          this.firstName=firstName;
      }
     // 可以设置 也可以不设置
      public voild setLastName(String lastName) {
          this.lastName=lastName;
      }
      // 可以设置 也可以不设置
     // 从数据绑定的角度来看,firstName  getFirstName() 这两个类是等效的。
     //用于 android:text 特性的表达式 @{user.} 访问前一个类中的 firstName 字段
     //或 getFirstName() 方法。或者如果该方法存在也将解析firstName()。
      public String getFirstName() {
          return this.firstName;
      }
      // 可以设置 也可以不设置
      public String getLastName() {
          return this.lastName;
      }
      // 会自动生成 allName 在xml 中调用
     public String getAllName (){
     return fitrName+lastName;
     }
    }
    
    // BaseActivity 的封装
    public abstract class BaseActivity<DB extends ViewDataBinding> extends AppCompatActivity {
    protected DB binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        beforeCreate(savedInstanceState);
        super.onCreate(savedInstanceState);
        if (getLayoutId() != 0) {
            binding = DataBindingUtil.setContentView(this, getLayoutId());
            binding.setLifecycleOwner(this);
        }
        initView();
        initData();
    }
    protected void beforeCreate(Bundle savedInstanceState) {}
    /**
     * 设置布局资源文件Id
     *
     * @return 返回布局Id
     **/
    protected abstract int getLayoutId();
    /**
     * 初始化控件
     **/
    protected abstract void initView();
    protected void initData() {}
    @Override
    protected void onDestroy() {
        super.onDestroy();
        ActivityManager.getInstance().removeActivity(this);
        if (binding != null) {
            binding.unbind();
        }
    }
}

表达式语言中使用以下运算符和关键字:
算术运算符 + - / * %
字符串连接运算符 +
逻辑运算符 && || (&需转义 &amp;)
二元运算符 & | ^
一元运算符 + - ! ~
移位运算符 >> >>> <<
比较运算符 == > < >= <=(请注意,< 需要转义为 &lt;)
instanceof
分组运算符 ()
字面量运算符 - 字符、字符串、数字、null
类型转换
方法调用
字段访问
数组访问 []
三元运算符 ?:

android:text="@{String.valueOf(index + 1)}"
    android:visibility="@{age > 13 ? View.GONE : View.VISIBLE}"
    android:transitionName='@{"image_" + id}'

缺少的运算
您可以在托管代码中使用的表达式语法中缺少以下运算:

this
super
new
显式泛型调用

Null 合并运算符
如果左边运算数不是 null,则 Null 合并运算符 (??) 选择左边运算数,如果左边运算数为 null,则选择右边运算数。
android:text=“@{user.displayName ?? user.lastName}”
这在功能上等效于:
android:text=“@{user.displayName != null ? user.displayName : user.lastName}”

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

视图引用
表达式可以通过以下语法按 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}"/>

注意:绑定类将 ID 转换为驼峰式大小写。

资源
表达式可以使用以下语法引用应用资源:
android:padding=“@{large? @dimen/largePadding : @dimen/smallPadding}”

看完这篇文章你就可以在你的项目中直接使用Databing了 如果项目中使用了ButterKnife 也可以新的页面直接使用不影响 ,剩下慢慢改造,本篇文章只是最基础的使用还有很多高级特性: 表达式连 lamde表达式 自定义属性 @BindingAdapter 转换动画等。 若对你学习DataBinding有帮助记的点赞。

官网地址

;