美文网首页
Android Jetpack之DataBinding

Android Jetpack之DataBinding

作者: itfitness | 来源:发表于2021-09-30 18:31 被阅读0次

    目录

    简单介绍

    DataBinding是Google在2015年的I/O大会上提出的,DataBinding可以帮助Android更好的实现MVVM架构,而且还可以省略像findViewById这样的代码,进一步降低了页面与布局文件直接的耦合度。

    使用方法

    1.开启DataBinding

    在app的build.gradle文件中增加如下代码

    android {
        ......
        dataBinding{
            enabled = true
        }
    }
    
    2.简单的数据绑定

    在开启了DataBinding之后我们可以在需要用到DataBinding的布局文件中,将鼠标移动到根标签上,就会自动提示让你点击变成DataBinding需要的格式



    这时候我们把需要绑定的数据在data标签中进行声明,而自定义的数据类型需要写全类名,数据的使用需要用@{},如下所示

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
    
        <data>
            <!--    基本数据类型    -->
            <variable
                name="price"
                type="int" />
            <!--    自定义数据类型    -->
            <variable
                name="book"
                type="com.example.databindingdemo.bean.Book" />
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:textSize="20sp"
                android:text="@{book.name}"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
            <TextView
                android:textSize="20sp"
                android:text="@{`价格¥:` + price}"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </layout>
    

    其中Book类如下

    public class Book {
        private String name;
    
        public Book(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    在Activity中绑定数据需要使用DataBindingUtil的setContentView方法,它会返回一个ViewDataBinding的对象,这里我们用的是系统自动生成的实现类,它生成的规则其实就是根据布局文件的名称来生成的,如下所示

    public class SimpleDataBindingActivity extends AppCompatActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivitySimpledatabindingBinding activitySimpledatabindingBinding = DataBindingUtil.setContentView(this,R.layout.activity_simpledatabinding);
            activitySimpledatabindingBinding.setBook(new Book("《斗罗大陆》"));
            activitySimpledatabindingBinding.setPrice(12);
        }
    }
    

    运行后的结果如下


    3.引入静态类

    在绑定数据的过程中我们可能需要对数据进行转化,因此我们可以通过引入静态类来实现,这里我们用的是import标签,如下所示

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
    
        <data>
            <!--   引入静态类     -->
            <import type="com.example.databindingdemo.util.DateUtil"/>
            <!--    基本数据类型    -->
            <variable
                name="week"
                type="int" />
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <TextView
                android:textSize="20sp"
                android:text="@{DateUtil.getWeek(week)}"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </layout>
    

    其中DateUtil类如下

    public class DateUtil {
        /**
         * 获取星期
         * @return
         */
        public static String getWeek(int num){
            switch (num){
                case 1:
                    return "星期一";
                case 2:
                    return "星期二";
                case 3:
                    return "星期三";
                case 4:
                    return "星期四";
                case 5:
                    return "星期五";
                case 6:
                    return "星期六";
                default:
                    return "星期天";
            }
        }
    }
    

    Activity中的使用如下:

    public class ImportDataBindingActivity extends AppCompatActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivityImportdatabindingBinding activityImportdatabindingBinding = DataBindingUtil.setContentView(this,R.layout.activity_importdatabinding);
            activityImportdatabindingBinding.setWeek(1);
        }
    }
    

    执行结果如下


    4.绑定点击事件

    这里绑定的是一个包含了点击事件的Model类,如下所示

    public class MainClickModel {
        private Context mContext;
    
        public MainClickModel(Context mContext) {
            this.mContext = mContext;
        }
    
        /**
         * 跳转简单绑定数据页面
         * @param view
         */
        public void onClickSimpleDataBinding(View view){
            mContext.startActivity(new Intent(mContext, SimpleDataBindingActivity.class));
        }
    }
    

    我们在布局文件中需要在onClick属性中增加绑定

    <?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"
        xmlns:tools="http://schemas.android.com/tools">
    
        <data>
            <variable
                name="mainClickModel"
                type="com.example.databindingdemo.model.MainClickModel" />
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MainActivity">
    
            <Button
                android:text="简单数据绑定"
                android:onClick="@{mainClickModel.onClickSimpleDataBinding}"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
    
        </LinearLayout>
    </layout>
    

    点击按钮效果如下


    5.自定义BindingAdapter

    DataBinding内部的数据填充都是通过BindingAdapter实现的,这里我们也可以通过自定义BindingAdapter来实现自己想要的功能,比如我们可以自定义一个ImageBindingAdapter来给ImageView添加网络图片

    public class ImageBindingAdapter {
        @BindingAdapter("netImage")
        public static void setNetImage(ImageView imageView,String imgUrl){
            Glide.with(imageView).load(imgUrl).into(imageView);
        }
    }
    

    布局文件如下,需要用app命名空间来使用自己自定义的BindingAdapter,其中名称要和自定义的BindingAdapter中@BindingAdapter注解中的名称一样

    <?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="netImageUrl"
                type="String" />
        </data>
    
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ImageView
                app:netImage="@{netImageUrl}"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
        </LinearLayout>
    </layout>
    

    Activity中的代码如下

    public class BindingAdapterActivity extends AppCompatActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivityBindingadapterBinding activityBindingadapterBinding = DataBindingUtil.setContentView(this,R.layout.activity_bindingadapter);
            activityBindingadapterBinding.setNetImageUrl("https://pic.netbian.com/uploads/allimg/180826/113958-1535254798fc1c.jpg");
        }
    }
    

    运行效果如下


    6.双向绑定

    目前以上所实现的只是用于展示的单向绑定,如果我们使用的是EditText这样需要输入数据的控件,就需要使用双向绑定了,这里我们使用来包装数据,如下所示我们定义一个Model然后把要绑定的数据使用ObservableField包装起来,然后添加set和get方法通过ObservableField返回

    public class ObservableFieldModel {
        private String userName = "唐三";
        private ObservableField<String> observableField;
    
        public ObservableFieldModel() {
            observableField = new ObservableField<>();
            observableField.set(userName);
        }
    
        public String getUserName() {
            return observableField.get();
        }
    
        public void setUserName(String userName) {
            observableField.set(userName);
        }
    }
    

    布局文件如下,这里不同的是双向绑定我们使用的是@={}

    <?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="observableFieldModel"
                type="com.example.databindingdemo.model.ObservableFieldModel" />
        </data>
    
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <EditText
                android:id="@+id/et"
                android:textSize="20sp"
                android:text="@={observableFieldModel.userName}"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </layout>
    

    Activity中的的逻辑如下,给EditText增加了一个文字改变时的监听,当文字改变后打印出当前变量的值

    public class ObservableFieldActivity extends AppCompatActivity {
    
        private ObservableFieldModel observableFieldModel;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivityObservablefieldBinding activityObservablefieldBinding = DataBindingUtil.setContentView(this,R.layout.activity_observablefield);
            observableFieldModel = new ObservableFieldModel();
            activityObservablefieldBinding.setObservableFieldModel(observableFieldModel);
            ((EditText)findViewById(R.id.et)).addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
                }
    
                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
    
                }
    
                @Override
                public void afterTextChanged(Editable editable) {
                    Log.e("双向绑定",observableFieldModel.getUserName());
                }
            });
        }
    }
    

    效果如下


    补充

    ●字符串拼接

    在布局文件中使用字符串拼接有如下几种方式
    1.string format
    其中name是布局文件中声明的变量

    <!--一个字符串-->
    <string name="Data_Text">Name is %s</string>
    android:text= "@{@string/Data_Text(name)}"
    
    <!--一个字符串-->
    <string name="Data_names">Name1: %1$s,Name2:%2$s</string>
    android:text= "@{@string/Data_names(name1, name2)}"
    

    2.加号方式(直接拼接)
    注意这里使用的不是单引号而是TAB键上面的那个键

    android:text="@{`字符串:` + str}"
    

    3.加号方式(string资源)

    android:text="@{@string/app_name+book.name}"
    

    案例源码

    https://gitee.com/itfitness/data-binding-demo

    相关文章

      网友评论

          本文标题:Android Jetpack之DataBinding

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