美文网首页
DataBinding的学习【2018-07-17】

DataBinding的学习【2018-07-17】

作者: jiaoheshang | 来源:发表于2018-07-23 09:21 被阅读0次

    一、基本的使用姿势

    1. module的build.gradle文件加上一行配置代码

    android {

        ...    dataBinding {

            enabled = true

        }}

    2. 创建布局文件

    只需要在之前布局的基础上,外层嵌套 即可。

                name="student"

                type="com.xiaweizi.bean.Student"/>

                    name="student"

                    type="Student"/>

            -->

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:gravity="center_horizontal"

            android:orientation="vertical">

    因为XML是不支持自定义导包的,所以通过import先导包,如果类名相同的话可以通过alias进行区分:

            alias="MyView"/>

        name="view1"

        type="View"/>

        name="view2"

        type="MyView"/>

    这个时候会在app\build\generated\source\debug\包名路径下生成对应的binding类,命名方式,举个例子最为直接:

    原XML名:activity_main  ----> 生成对应的binding名: ActivityMainBinding

    3. Activity中替换原来的setContentView()代码

    ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

    二、事件的binding

    1.单向binding

    案例1:(view id)

        android:id="@+id/tv_content"

        android:text="@{student.name}"

        android:layout_width="match_parent"

        android:layout_height="50dp"/>

    在代码中通过binding直接可以获取到这个TextView

    mBinding.tvContent

    案例2:(click event)

    ①定义按键处理的类型

    public class Presenter {

          //Android标准的事件类型,需要注意Method中的参数和api中的保持一致

    public void onTextChanged(CharSequence s, int start, int before, int count) {

                employee.setFirstName(s.toString());

                employee.setFired(!employee.isFired.get());

                //binding.setEmployee(employee);

            }

    //自定义的事件类型

            public void onClickListenerBinding(Employee employee) {

                Toast.makeText(SimpleActivity.this, employee.getLastName(),

                        Toast.LENGTH_SHORT).show();

            }

        }

    ②、在xml中声明制定的案件处理的类型和指定事件

                name="presenter"

                type="com.github.markzhai.sample.SimpleActivity.Presenter"/>

    //Android标准的事件类型

                android:id="@+id/et_first_name"

                android:layout_width="match_parent"

                android:layout_height="wrap_content"

                android:hint="输入 First Name jiaoyin"

                android:onTextChanged="@{presenter::onTextChanged}"/>

    //自定义的事件类型

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_marginLeft="5dp"

                android:onClick="@{() -> presenter.onClickListenerBinding(employee)}"

                android:text="@{employee.lastName}"/>

    2.双向binding

    之前说的单向绑定,即当数据变化,通过mBinding.setStudent(student)方式驱动UI的改变

    而双向绑定,无论View还是ViewModel谁改变,都会驱动另一方的改变,实现双向绑定有两种方式:继承BaseObservable或者使用ObservableField创建成员变量。

    案例1:继承BaseObservable:

    public class Employee extends BaseObservable {

        private String mLastName;

        private String mFirstName;

        public Employee(String lastName, String firstName) {

            mLastName = lastName;

            mFirstName = firstName;

            isFired.set(false);

        }

        @Bindable

        public String getLastName() {

            return mLastName;

        }

        public void setLastName(String lastName) {

            mLastName = lastName;

            notifyPropertyChanged(com.github.markzhai.sample.BR.lastName);

    //notifyChange();

        }

    }

    这个时候当调用setLastName()方法,不仅数据改变,UI中的TextView内容也会随之改变。

    我们可以发现有两个方法:notifyPropertyChanged()和notifyChange,一个是更新指定的变量,第二个是更新所有该ViewModel中的对象。

    而notifyPropertyChanged(int fieldId)里面传的参数,即上面通过@Bindable注解创建对应的变量id。

    案例2:使用ObservableField创建成员变量

    public class Employee extends BaseObservable {

        private String mLastName;

        private String mFirstName;

        public ObservableArrayMap user = new ObservableArrayMap<>();

        private String mAvatar;

        public ObservableBoolean isFired = new ObservableBoolean();

        public Employee(String lastName, String firstName) {

            mLastName = lastName;

            mFirstName = firstName;

            isFired.set(false);

        }

        public void setFired(boolean fired) {

            isFired.set(fired);

        }

        @Bindable

        public String getAvatar() {

            return mAvatar;

        }

        public void setAvatar(String avatar) {

            mAvatar = avatar;

        }

    }

    通过使用ObservableField创建的对象作用相当于第一种的方案,支持ObservableInt、ObservableBoolean或者是ObservableField指定的类型、ObservableArrayMap、ObservableArrayList等。

    ObservableField内部已经封装了get和set方法,如果成员变量是public属性,直接通过

    mStudent.name.set("shabi");

    String name = mStudent.name.get();

    设置和获取对应的成员变量的值。

    其他用法:

    2. ViewStub和include

    dataBinding同样是支持ViewStub的,使用起来也很简单,直接贴代码了。

        android:id="@+id/view_stub"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout="@layout/viewstub"/>

    代码中:

    View inflate = binding.viewStub.getViewStub().inflate();

    inflate即为替代ViewStub的View.

    至于include更简单,用法跟以前是差不多,唯一不同的是可以将ViewModel传到下一个XML中:

    bind:student="@{student}"/>

    layout_include中同样可以共享student这个对象。

    3.  @BindingConversion

    dataBinding还支持对数据的转换,或者是类型的转换

    4.自定义的属性之BindingAdapter的使用

    案例:

    //1、xml定义

    android:id="@+id/username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="35sp"

    android:text="@{user.name}"/>

    //2、BindingAdapter自定义

    public class TextViewBindingAdapter {

    @BindingAdapter("android:text")

    public static voidsetText(TextView view, CharSequence text) {

            final CharSequence oldText = view.getText();

            if (text == oldText || (text == null && oldText.length() == 0)) {

                return;

            }

            if (text instanceof Spanned) {

                if (text.equals(oldText)) {

                    return; // No change in the spans, so don't set anything.

                }

            } else if (!haveContentsChanged(text, oldText)) {

                return; // No content changes, so don't set anything.

            }

            view.setText(text);

        }

    }

    //3、更新User的name的值

    User user = new User(name, age);

    mBinding.setUser(user);

    databinding框架,会做如下几件事情:

    ①计算出@{user.name} 表达式的值;

    ②寻找合适的BindingAdapter,如果找到,就调用它对应BindingAdapter里面的(setText)方法;

    ③如果没有找到合适的BindingAdapter,就在View上寻找合适的(setText)方法调用;

    如此类推,可以自定义BindingAdapter..............

    5. DataBindingComponent

    通过BindingAdapter是可以增加一些自定义的属性或者是修改Android原生的属性,但是它有一个弊端,就是全局修改所有的相关属性,不过配合上DataBindingComponent就可以解决这个问题。

    6.RecyclerView中的应用

    案例:

    //xml定义部分:

        xmlns:android="http://schemas.android.com/apk/res/android">

                name="presenter"

                type="com.github.markzhai.sample.ListActivity.Presenter"/>

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:orientation="vertical">

                android:id="@+id/recycler_view"

                android:layout_width="match_parent"

                android:layout_height="match_parent"/>

    //初始化 recycleview 和 adapter部分

    protected void onCreate(@Nullable Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            mBinding = DataBindingUtil.setContentView(this, R.layout.activity_list);

            mBinding.setPresenter(new Presenter());

    mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(this));

    mEmployeeAdapter = newEmployeeAdapter(this);

    mBinding.recyclerView.setAdapter(mEmployeeAdapter);

            List demoList = new ArrayList<>();

            demoList.add(new Employee("Zhai", "Mark", false));

            demoList.add(new Employee("Zhai2", "Mark2", false));

            demoList.add(new Employee("Zhai3", "Mark3", true));

            demoList.add(new Employee("Zhai4", "Mark4", false));

    mEmployeeAdapter.addAll(demoList);

        }

    //自定义viewholder部分

    public class BindingViewHolder

            extends RecyclerView.ViewHolder {

        private T mBinding;

        public BindingViewHolder(T binding) {

    //注意,这里是要设置 binding的rootview 给到viewholder中

          super(binding.getRoot());

            mBinding = binding;

        }

        public T getBinding() {

            return mBinding;

        }

    }

    //自定义adapter部分

    public class EmployeeAdapter extends RecyclerView.Adapter {

    @Override

        public BindingViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            ViewDataBinding binding;

            if (viewType == ITEM_VIEW_TYPE_ON) {

    //加载出 DataBinding的对象

    binding =DataBindingUtil.inflate(mLayoutInflater,

                        R.layout.item_employee, parent, false);

            } else {

    binding =DataBindingUtil.inflate(mLayoutInflater,

                        R.layout.item_employee_off, parent, false);

            }

    //注意

    returnnew BindingViewHolder(binding);

        }

        @Override

        public void onBindViewHolder(BindingViewHolder holder, int position) {

            final Employee employee = mEmployeeList.get(position);

    //注意:

    //设置 variable变量,并内部有去做 notifyDataChange的动作

            holder.getBinding().setVariable(com.github.markzhai.sample.BR.item, employee);

    //execute,以便马上更新

            holder.getBinding().executePendingBindings();

        }

    相关文章

      网友评论

          本文标题:DataBinding的学习【2018-07-17】

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