美文网首页
DataBinding的用法

DataBinding的用法

作者: 幼稚的逗逗逗逗比 | 来源:发表于2018-10-18 18:04 被阅读55次

    DataBinding的用法

    • 是时候抛弃ButterKnife,拥抱DataBinding了。
      1.ButterKnife对组件化方案支持不如DataBinding
      2.ButterKnife只支持View绑定,不支持数据绑定
      3.DataBinding是Google出品。
      就算只看第三条,你也知道选哪个了吧 (手动滑稽)下面还有更多DataBinding的优点

    启用DataBinding

    android {
        dataBinding {
            enabled true
            }
    }
    

    ***注意:如在lib中也使用DataBinding也需要在build文件中添加 ***

    DataBinding 的基本使用

    数据绑定

    我们创建一个User类,User有两个属性:name和age。

    public class User {
        private String name;
        private int age;
        public User() {
            this.name = "小花";
            this.age = 18;
        }
        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; }
    }
    

    也可以这样写

    public class User {
        public String name;
        public int age;
    }
    

    然后我们想把User这个对象的两个属性绑定在xml控件中,我们创建一个activity_main.xml文件.因为age属性是int类型,而textView.setText()不允许使用int,所以,我们可以在后面拼上字符标志``

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <data>
            <variable
                name="user"
                type="com.example.ding.databindingdemo.User" />
        </data>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{user.name}" />
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{user.age+`岁`}" />
        </LinearLayout>
    </layout>
    

    然后我们在Activity中获取xml对应的DataBinding对象,并对其进行赋值

        private ActivityMainBinding mBinding;//这个对象是根据activity_main.xml命名规则自动生成的,继承自ViewDataBindig了;类
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
            mBinding.setVariable(BR.user,new User());
            //或者
            mBinding.setUser(new User());
            mBinding.executePendingBindings();
        }
    

    fragment这样绑定DataBindingUtil.inflate(inflater,R.layout.fragment_home,container,false);

    是不是很简单?这还简单的,看的我头皮发麻,两眼发晕,我不需要绑定什么数据,我就想跟ButterKnife用法一样。好,下面就满足你

    控件绑定

    我们在xml中为每个你需要拿到的控件命名ID

            <Button
                android:id="@+id/main_btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
    

    那我们应该怎么拿到对应的控件呢?就是我们的ViewDataBinding的子类,生成的ActivityMainBindingButton mBinding.mainBtn(生成规则遵循Java驼峰命名),这样我们就可以拿到这个按钮了,之后的事情就不用我说了把。

    方法绑定

            <Button
                android:id="@+id/main_btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:onClick="onClick"/>
    

    以前我们可以这样写点击事件,然后在activity中定义public void onClick(View view) { }方法,然后在这里面对点击事件进行处理。现在,我们可以对这个点击事件做任何方法的跳转。传入类,mBinding.setVariable(BR.act,this);然后传入类方法android:onClick="@{()->类对象.类方法(参数para)}"

            <variable
                name="act"
                type="com.example.ding.databindingdemo.MainActivity"/>
            <Button
                android:id="@+id/main_btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:onClick="@{()->act.getName(user.name)}"/>
    

    我们在activity中定义的方法public void getName(String name){ //todo }。当然,你也可以导入其他类。例如定义MyHandlers

    public class MyHandlers {
        public void getName(String name) { ... }
    }
    

    布局文件就要这样写。

        <variable
                name="handler"
                type="com.example.ding.databindingdemo.MyHandlers"/>
            <Button
                android:id="@+id/main_btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:onClick="@{()->handler.getName(user.name)}"/>
    

    注意:要在Activity中传入MyHandlers实例,不然会报空指针。

    自定义方法Binding adapters

    有些控件不能直接传数据就能展示,例如ImageView,RecyclerView之类。我们可以用BindingAdapter注解来自定义方法,xml中使用方式:

    <ImageView 
           android:layout_width="wrap_content"
           android:layout_height="wrap_content" 
           bind:imageUrl="@{user.pic}" />
    

    新建一个java类,类名随意。类方法需为static@BindingAdapter注解标记该方法,valueStirng[],xml中使用的atts与里面的命名规则一致。requireAll是否必须传。然后在setImageUrl方法中获取view和url参数,然后进行展示。当然url也可以替换为src或者bitmap

    public class ImageBindingAdapter {
        @BindingAdapter(value = {"bind:imageUrl"},requireAll = true)
        public static void setImageUrl(ImageView view,String url){ 
            Glide.with(view.getContext()).load(url).into(view);
        }
       @BindingAdapter(value = {"bind:imageSrc"},requireAll = true)
        public static void setImageSrc(ImageView view,int src){
            view.setImageResource(src);
        }
        @BindingAdapter(value = {"bind:imageBitmap"},requireAll = true)
        public static void setImageBitmap(ImageView view,Bitmap bitmap){
            view.setImageBitmap(bitmap);
        }
    }
    

    假如你写了一个自定义控件,你也可以用@BindingAdapter绑定你的数据源。例如,我写了一个MyLinearLayout来实现ListView,然后我写了一个text_list方法来传递数据。

    <com.ding.example.MyLinearLayout 
           android:layout_width="wrap_content"
           android:layout_height="wrap_content" 
           bind:text_list="@{user.datas}" />
    

    java代码

    public class LinearLayoutBindingAdapter {
        @BindingAdapter(value = {"bind:text_list"},requireAll = true)
        public static void setDataResource(MyLinearLayout layout,List datas){ 
            layout.setDataList(datas);
        }
    

    这样,我们就把数据源传到我们的MyLinearLayout中,然后在我们自定义的LinearLayout中对数据做处理了。

    双向绑定

    双向绑定使用@={}就可以实现了。没错,就是这么简单。例如,EditText中双向绑定了user.job这个属性,当editText中内容发生更改时,绑定的数据user.job也会更新,通过mBinding.getUser().job就可以拿到最新的数据了。

    表达式

    • 数学运算符: + - / * %
    • 字符串拼接: +
    • 逻辑运算符: && ||
    • 二进制: & | ^
    • 一元运算符: +
    • 位运算符: >> >>> <<
    • 比较: == > < >= <=
    • instanceof
    • ()<
    • 数据类型: character, String, numeric, null
    • 类型转换(ClassCast)
    • 方法回调(Method calls)
    • 数据属性
    • 数组:[]
    • 三元操作符:?

    与LiveData连用

    LiveData是谷歌新推出的一个可被观察的数据持久化的控件,通常出现在ViewModel中,是用用MVVM架构。有兴趣的看一下我的上一篇文章基于Google MVVM框架的baseMVVM框架
    LiveData遵循其他应用程序控件的生命周期,例如Activity,Fragment或Service。此感知确保LiveData仅更新处于活动生命周期状态的应用程序控件观察者,不会造成内存泄漏。具体是用请参考官方文档

    • 注意:DataBinding需调用setLifecycleOwner(LifecycleOwner lifecycleOwner)之后,绑定了LiveData数据源的xml控件才会随着数据变化而改变。
    • 注意:LiveData暴露公开两个方法用于设置值:
      1.postValue:允许后台线程向主进程推送数据
      2.setValue:只允许在主线程调用,如果在其他线程调用会报错:This method must be called from the main thread
      最后奉上demo的github地址 https://github.com/dingdaidao/DataBindingDemo

    相关文章

      网友评论

          本文标题:DataBinding的用法

          本文链接:https://www.haomeiwen.com/subject/uenqzftx.html