DataBinding

Data Binding

优势

  • MVVM
  • 去掉Activity&Fragment内的UI代码
  • 减少FindViewById代码的作用
  • 类似方案 ButterKnife , Android Annotations ,Robo Binding

劣势

  • IDE支持不完善
  • 报错信息不直接
  • 没有重构支持

配置

App Module的android标签内 开启:

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

基础语法

用法一 :去除findViewById

在原layout文件外套一层标签

<layout >
      //原来的layout  命名空间上移
 </layout>
 
 //生成规则是根据布局文件来生成的 例:activity_main ->  ActivityMainBinding
  ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main); 替换掉setContentView(R.layout.activity_main)
 

这个时候就 不用findViewById来获取控件了,而是用Binding.xxxView 代替

用法二 : 去除fbi的同时设置初始数据

<layout >
      <data>
          <variable 
           name="employee"
           type="net.hongqian.better.databingdemo.Employee"/>
      </data>
     //原来的layout  命名空间上移
</layout>
<LinearLayout>
       <TextView
           ...
           android:text="@{employee.name}" />
       <TextView
           ...
           android:text="@{employee.pwd}" />
   </LinearLayout>

binding.setEmployee(Employee对象)或者
binding.setVariable(BR.employee,Employee对象); 都能达到同样效果

用法三 :UI/事件绑定

  • Bind UI## setVariable ,setXXX
  • 事件 onClick ,onLongClick ,onTextChanged ...
方法一:方法引用
<layout >
    <data>
        <variable
            name="employee"
            type="net.hongqian.better.databingdemo.Employee"/>
          <variable
              name="presenter"                                              type="net.hongqian.better.databingdemo.MainActivity
              .Presenter"/>
</data>
    <LinearLayout>
        <TextView
        ...
            android:id="@+id/tv_name"
            android:text="@{employee.name}"
            android:onClick="@{presenter.onClicked}" />
        <EditText
           ...
            android:id="@+id/tv_pwd"
            android:onTextChanged="@{presenter.onTextChanged}"/>
    </LinearLayout>
</layout>

代码中使用

        binding.setVariable(net.hongqian.better.databingdemo.BR.employee, employee);
        binding.setPresenter(new Presenter());
        
         public class Presenter {
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            employee.setName(charSequence.toString());
            binding.setEmployee(employee); //重新设置一下employee
        }

        public void onClicked(View view) {  //方法名可以不一样,但是参数要一样
            Toast.makeText(MainActivity.this, "点击事件发生了!", Toast.LENGTH_SHORT).show();
        }
    }
方法二:监听器绑定语法 lamda表达式
<TextView
            android:id="@+id/tv_name"
            android:onClick="@{() ->presenter.onClickListenerBinding(employee)}" />
  public class Presenter {
        public void onClickListenerBinding(Employee employee){
            Toast.makeText(MainActivity.this, employee.getName(), Toast.LENGTH_SHORT).show();
        }
} 

表达式

  • 二元运算符 & | ^
  • 一元运算符 + - ! ~
  • 移位 >> >>> <<
  • 比较 == > < >= <=
  • Instanceof
  • Grouping ()
  • Cast
  • Array [] 访问
  • 三元运算符 ?
  • this super new 显示泛型调用不支持
  • 取非空表达式 android:text = "@{user.displayName ?? user.lastName}"
    相当于 android:Text="@{user.displayName!=null ? user.displayName: user.lastName}"
  • 设置尺寸时可以这样写 @dimen + @dimen 将引入的dimen相加

Include

     <include
            layout="@layout/include_demo"
            bind:employee="@{employee}"/>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="employee"
            type="net.hongqian.better.databingdemo.Employee" />
    </data>
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@{employee.name}" />
    </FrameLayout>
</layout>

observable

一,baseObservable

使用Bindable注解的属性 当其发生变化时 会使相应的UI层发生变化:
我们需要在getter方法上添加Bindable注解后,Bindable注解会自动生成一个BR类,该类位于app module包下,通过BR类我们设置更新的数据,当Model中的数据发生变化时,setter方法中的notifyPropertyChanged()就会通知UI更新数据了。

public class Employee extends BaseObservable {
    private String name;
    private String pwd;
    public Employee(String name, String pwd) {
        this.name = name;
        this.pwd = pwd;
    }
    @Bindable   
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);  //通知
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}
  public class Presenter {
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            employee.setName(charSequence.toString()); 

    }
<layout >
    <data>
        <variable
            name="employee"
    type="net.hongqian.better.databingdemo.Employee" />
        <import type="android.view.View"/> //引入类型
    </data>
    <FrameLayout
        android:visibility="@{employee.getIsFired? View.GONE:View.VISIBLE}"  //使用引入的类型
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="@{employee.name}" />
    </FrameLayout>
</layout>

方法名要使用getXXX() setXXX()这样的 不然编译会报错

  private boolean isFired;
    @Bindable
    public boolean getIsFired() { 
        return isFired;
    }
 public void setFired(boolean fired) {
        isFired = fired;
        notifyPropertyChanged(BR.isFired);
    }

二,Observable Fields

我们刚刚介绍的通知UI更新的方法是用User类继承自BaseObservable,然后在getter上添加注解、在setter中添加notify方法,这感觉总是有点麻烦,步骤繁琐,于是,Google推出ObservableFields类,使用它我们可以简化我们的Model类

 private ObservableBoolean isFired=new ObservableBoolean(); //创建对象
    public boolean getIsFired() {
        return isFired.get();
    }

    public void setFired(boolean fired) {
        isFired.set(fired);
        notifyChange();
    }
应用:
 employee.setFired(!employee.getIsFired());

三,Observable Collection

包括 ObservableArrayMap ,ObservableArrayList

 public ObservableArrayMap<String,String> map=new ObservableArrayMap<String, String>();
   public Employee(String name, String pwd) {
        this.name = name;
        this.pwd = pwd;
        isFired.set(false);
        map.put("hello","word");
        map.put("hi","word1");
        map.put("hi","word2");
    }
 <TextView
           ...
            android:text='@{employee.map["hello"]}'
         />
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容