Android从零开始搭建MVVM架构(2)——Databinding之BindingAdapter

2022-06-22 13:03:48 浏览数 (1)

在上一篇文章《Android从零开始搭建MVVM架构(1)——Databinding入门》中,我们已经学习了Databinding的基础使用,本篇我们来学习BindingAdapter的用法,我们经常会使用自定义控件还有Android的一些控件,如RecyclerView等,当我们在这些控件的属性,就需要用到BindingAdapter,例如如下的情况:

代码语言:javascript复制
 <com.gcssloop.widget.ArcSeekBar
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:padding="10dp"
            app:arc_colors="@array/arc_colors_custom"
            app:arc_max="100"
            app:arc_min="0"
            app:arc_open_angle="0"
            binding:arc_progress="@{viewModel.currentProgress}"
            app:arc_rotate_angle="270"
            app:arc_thumb_color="#fff"
            app:arc_thumb_mode="FILL"
            app:arc_thumb_radius="5.5dp"
            app:arc_width="4dp"
            />

这个控件中有一个自定义属性arc_progress,针对于这个属性就需要使用BindingAdapter进行绑定

为什么会有BindingAdapter

我们先来看一个布局:

代码语言:javascript复制
 <TextView
                android:id="@ id/user_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{user.name}"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

当我们给name设值为“Jack”的时候,DataBinding要做的事情就是:要把值为的“Jack”的字符串赋值给TextView的命名空间为android的text属性。

如果是你写DataBinding,面对上面的情况,也许会这样做:

1.忽略命名空间android

2.根据属性值text和binding表达式的值CharSequence “Jack”在TextView中寻找有如下签名的方法:

setText(CharSequence text)

3.在id为user_name的TextView上调用:setText(“Jack”)

但这样会带来什么问题?我个人思考如下:

1.不够灵活,比如text的值从未发生过改变呢,重复设置不是浪费资源?造成性能的消耗

2.如果我有特定的需求,在某些情况下才值绑定进去,这样就灵活处理

3.如果一些第三方控件,它里面设置text的方法不叫setText(CharSequence text),而是setChar(CharSequence text),那岂不是找不到方法了?

为了让我们能更加灵活的进行数据绑定,就引出了BindingAdapter

使用BindingAdapter

Android Databinding框架中已经为我们准备了大部分控件的一些属性的BindingAdapter,就比如上面的TextView:

代码语言:javascript复制
@BindingAdapter("android:text")
    public static void setText(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);
    }

将上面这个BindingAdapter注解的方法总结就是:

当在TextView上设置text属性,且设置的值的类型是CharSequence时,就不要直接调用TextView相应的setText方法,而是调用用户定义的这个BindingAdapter方法。

声明:BindingAdapter注解的方法取什么名字都行,因为压根不关心这个方法的名字,BindingAdapter只需要通过"android:text",TextView,CharSequence 这3个就可以确定出唯一的方法

从上图可以看出Databinding框架中已经写好了很多Android自身控件的BindingAdapter

自定义BindingAdapter

回到文章一开始提到的,如果是第三方控件,或者我们自己的自定义控件,那我们就需要自己定义BindingAdapter了,如何使用?还是拿文章一开始的自定义控件为例子

代码语言:javascript复制
 <com.gcssloop.widget.ArcSeekBar
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:padding="10dp"
            app:arc_colors="@array/arc_colors_custom"
            app:arc_max="100"
            app:arc_min="0"
            app:arc_open_angle="0"
            binding:arc_progress="@{viewModel.currentProgress}"
            app:arc_rotate_angle="270"
            app:arc_thumb_color="#fff"
            app:arc_thumb_mode="FILL"
            app:arc_thumb_radius="5.5dp"
            app:arc_width="4dp"
            />
代码语言:javascript复制
 <data>
        <import type="android.view.View"/>
        <variable
            name="viewModel"
            type="com.demo.viewmodel.TestViewModel" />
    </data>

我的自定义BindingAdapter写法如下

代码语言:javascript复制
public final class ArcSeekBarAdapter {

    @SuppressWarnings("unchecked")
    @BindingAdapter(value = {"app:arc_progress"})
    public static void setProgress(ArcSeekBar arcSeekBar, int progress) {
        arcSeekBar.setProgress(progress);
    }
}

通过上面这些代码就可以实现自定义控件的数据绑定

0 人点赞