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

<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

我们先来看一个布局:

<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:

@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个就可以确定出唯一的方法

Android从零开始搭建MVVM架构(2)——Databinding之BindingAdapter_开发语言

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

自定义BindingAdapter

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

<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"
            />
<data>
        <import type="android.view.View"/>
        <variable
            name="viewModel"
            type="com.demo.viewmodel.TestViewModel" />
    </data>

我的自定义BindingAdapter写法如下

public final class ArcSeekBarAdapter {

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

更多Android进阶指南 

1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2024最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔