Jetpack学习-7-Databinding的基本使用及单向&双向绑定

DataBinding是Jetpack中比较受非议的一个库,很多开发者不习惯且不喜欢在xml布局中进行java层代码的数据绑定,如果是简单的页面,用不上databinding,而复杂的页面,用了databinding对后续的问题排查又是个蛋疼的事,但不妨碍学习databinding的使用。

优点:

1,UI控件的代码在布局中编写,降低页面与布局文件的耦合度

2,不需要写findviewById(viewbinding表示它也可以)

3,布局文件可以包含简单的业务逻辑(个人不建议)

使用基本操作

1,在app的build.gradle文件中开启数据绑定功能

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

2,修改布局文件

将光标移到根目录,会出现小灯泡,点击,选择 Convert to data binding layout(转变为databinding布局)Jetpack学习-7-Databinding的基本使用及单向&双向绑定_第1张图片

 自动生成如下内容

activity_main6.xml




    

    

    

        

    

也可以手动添加 等标签转变布局

rebuild后会自动生成对应的binding类Jetpack学习-7-Databinding的基本使用及单向&双向绑定_第2张图片

3,使用绑定类

databinding    

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMain6Binding activityMain6Binding = DataBindingUtil.setContentView(this, R.layout.activity_main6);
        activityMain6Binding.tvMessage.setText("hello,databinding");
    }

另比较viewbinding的使用

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMain5Binding binding = ActivityMain5Binding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        binding.tvMessage.setText("hello,viewbinding");
        
    }

可以看出,viewbinding就是databinding的子类,底层也是databinding来实现的,数据绑定离不开识图的绑定

4,布局中设置变量并进行控件绑定



    //用于放置布局中控件所需要的变量

        

        

        
    

    

        

        

        

        

    

5,将数据引入到布局中

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMain6Binding activityMain6Binding = DataBindingUtil.setContentView(this, R.layout.activity_main6);
        activityMain6Binding.tvMessage.setText("hello,databinding");

        //第一种方式(个人推荐这种方式,这种方式可以强制设置属性的类型,避免很多传参问题,同时也不会把其他布局的变量进行设置)
        activityMain6Binding.setAge(12);//传入整型时会默认为资源id,要进行二次处理
        activityMain6Binding.setName("sunguanyong");
        activityMain6Binding.setStudent(new Student("hanmeimei", 14));

        //第二种方式(BR类似于项目的R文件,管理所有布局变量的id,这里必须传入正确的id才能传好数据,而且无法跳转到布局中的变量位置,所以不推荐)
        activityMain6Binding.setVariable(BR.age, 12);
        activityMain6Binding.setVariable(BR.name, "sunguanyong");
        //activityMain6Binding.setVariable(BR.name1, "sunguanyong");//这个name1是另一个布局中的变量,也能进行设置操作,这就很容易引起错误,实际不会崩溃,但没有作用
        activityMain6Binding.setVariable(BR.student, new Student("hanmeimei", 15));
    }

这样,最基本的databinding的使用已经完成,下面拓展别的用法。

6,布局中绑定静态方法

1,静态方法 
package com.sun.databinding;

public class StaticMethod {
    public static String getName() {
        return "sunguanyong 2022";
    }

    public static String getName(int age) {
        return "hello ,lilei ," + age;
    }
}


2,布局中导入并引用

        ...
        


3,调用静态方法
 

7,绑定点击事件

1,在页面中设置点击逻辑
 /**
     * 点击事件
     */
    public class EventClick {

        private Context context;

        public EventClick(Context context) {
            this.context = context;
        }

        public void clickToast(View view) {
            Log.e(TAG, "view的id=" + view.getId() + "   " + ((Button) view).getText());//id=-1,因为我没有设置id
            Toast.makeText(context, "我通过 EventClick databind了", Toast.LENGTH_SHORT).show();
        }
    }


2,在布局中使用添加EventClick的实例

    
        ...
        
    

3,绑定到button的点击事件中
  

8,二级页面传值,所谓的二级页面其实是对布局中layout包裹的布局进行传值

1,二级页面简单编写



    
        
    

    

        
        
    



2,添加二级布局,同时根据二级页面的变量进行传值
//给studentinfo的变量传入值,值为页面传来的student

上面的数据绑定操作都是单向操作,页面更改数据从而导致布局显示变化,也可以实现双向绑定。

9,要想实现双向绑定,肯定离不开观察者模式,双向绑定也是这一模式的具体体现

方法1(使用BaseObservable)

1,建立 被观察类

public class StudentObservable extends BaseObservable {

    public String name;

    public StudentObservable(String name) {
        this.name = name;
    }

    @Bindable    //告诉编译器,对这个字段进行双向绑定
    public String getName(){
        return name;
    }

    public void setName(String name){//数据发生变化时自动调用,也可以主动调用
        if(!TextUtils.isEmpty(name)&&!this.name.equals(name)){
            this.name=name;
            notifyPropertyChanged(BR.name);//使用BaseObservable中的notifyPropertyChanged(BR.id)进行通知
        }
    }
}


2,布局显示

        ...
        



 //此处用@=,可接收属性的数据更改并同时监听用户更新

//此处用@=

使用这种方法必须继承自BaseObservable成为被观察者,另外,在Getter方法添加@Bindable标签,在setting中进行notifyPropertyChanged(),也可以通过更简单的ObservableField的方式实现双向绑定。

方法2(使用ObservableField)

1,创建类
package com.sun.databinding;

import androidx.databinding.ObservableField;

public class StudentObservableField {

    //ObservableField可以看成是对BaseObservable,set,get, @Bindable,notify进行了封装
    //基本数据类型:ObservableInt,ObservableFloat等
    public ObservableField name;

    public StudentObservableField(String name) {
        this.name = new ObservableField(name);
    }

}

2,布局及使用同BaseObservable是一样的

        ...
        

    



        

        

BaseObservable与ObservableField的比较:

看源码知道ObservableField是对BaseObservable进行了封装,站远一点分析,属性依附在对象中,BaseObservable作用在对象上,所以需要继承才能让内部的属性可以双向数据绑定,而ObservableField则作用在属性上,直接做了封装,所以类就不用做特殊处理显得更加简单。

至此,databinding的初步使用已经完成,如果再看官网的整个流程的话,还是有很多东西没有覆盖到的。虽然很多时候databinding在开发过程中饱受争议,但不妨碍我们学习使用它,内部的实现很多地方还是值得学习的。

这一篇只介绍使用,下一篇开始将深入接触bindingAdapter的使用和对databinding的源码分析。

Android-Jetpack代码位置:github

你可能感兴趣的:(android,android,jetpack)