Android-DataBinding-使用-高阶

概述

  • 本节是针对只会简单使用DataBinding的开发;

变量

  • 在XML中声明的变量分为两种,可观察变量和不可观察变量;可观察变量是指implement了Observable/ObservableList/ObservableMap接口或者是LiveData及子类的对象;其他的则是不可观察变量;可观察变量在变量的某个子属性发生变化时,也会触发自动更新UI,非可观察变量则只有在修改该变量或者调用invalidateAll时,才会触发自动更新UI;

  • Bindable

    • Bindable可以应用在Observable实现类的getter方法上,在修改对应属性后,可以通过BR.attrName进行修改通知;
    • Bindable注解可以添加多个依赖属性,当任意一个属性发生变更(onPropertyChanged)时,和该Bindable绑定的表达式将重新计算;
  • 可观察变量有两种实践方式:一种是在XML中声明多个可观察变量,每个变量都是可观察的;另外一种是在XML中声明极少的实现了Observable的类实例(一个XML最好对应一个可观察变量),变量的属性可以通过Bindable注解达到可观察的目的;

    • 个人推荐第二种,结合ViewModel也是一种很好的实践;
    • 对于基本类型(int,char,long,String)的数据,数据本身不需要具备可观察特性,通过Bindable注解即可,对于自定义类型,最好是扁平型的,通过实现Observable接口和Bindable注解也可以达到属性可观察;
    • 对于多层级的自定义类,如果修改最内层的属性,则无法达到可观察自更新效果;从XML中定义的变量开始,最多能实现两层的可观察自更新属性;

绑定表达式

  • 绑定表达式在Databinding中是非常重要的概念,在编译期间,就是通过声明的表达式将View组件绑定到相关数据源,进而生成相关类;
  • 绑定表达式是在XML中@{}@={}中的表达式;
  • 中声明的变量可以在绑定表达式中直接使用;
  • 绑定表达式支持的运算符和关键字
    • 算术运算符 + - / * %
    • 字符串连接运算符 +
    • 逻辑运算符 && ||
    • 二元运算符 & | ^
    • 一元运算符 + - ! ~
    • 移位运算符 >> >>> <<
    • 比较运算符 == > < >= <=(请注意,< 需要转义为 <)
    • instanceof
    • 分组运算符 ()
    • 字面量运算符 - 字符、字符串、数字、null
    • 类型转换
    • 方法调用
    • 字段访问
    • 数组访问 []
    • 三元运算符 ?:
    • Null 合并运算符 ??
    • 属性引用.
    • 集合操作[],可用于数组,列表,映射;
    • 字面常量
    • 资源@,但是有些资源类型需要显式指明;
  • 不能使用的运算
    • this
    • super
    • new
    • 显式泛型调用
  • 事件处理
    • 事件处理分为两种:方法引用和监听器绑定;
    • 方法引用:在编译时处理,如果方法不存在或者方法签名与监听器中的方法签名不匹配,则触发编译时错误;在数据绑定时进行创建监听器,如果表达式求值为null,则不创建,否则创建;
    • 监听器绑定:在触发事件时,对表达式进行求值;只要返回类型匹配就可以;
  • include嵌套
    • 当XML中通过include嵌套了另一个XML时,可以通过bind: + 被嵌套XML中声明的变量名将XML中的数据传给被嵌套的XML;
  • 不建议在XML中写复杂表达式,应尽量移到数据源中;

BindingAdapter

  • BindingAdapter注解在方法上,用于将绑定表达式的值设置到对应的View组件上;
  • BindingAdapter注解方法格式应该为:
    @BindingAdapter(value = {"attr1","attr2",...}, requireAll = true)
    public static void methodName(View view, Type... old, Type... new);
    
    • 类方法,第一个参数类型为View组件类型,后面的为对应的属性类型,所有的旧值放在前面,新值放在后面,属性个数必须和值个数相等;
    • requireAll为true时,只有所有的属性都有绑定表达式时,才会匹配;requireAll为false,只要有一个属性有绑定表达式,也会匹配到该方法;
  • 事件处理,只能与一种具有抽象方法的接口或抽象类一起使用;监听器有多个方法时,需要拆分为多个监听器;

BindingConversion

  • BindingConversion用于将表达式的值类型转化为BindingAdapter方法接收的值类型;
  • BindingConversion是全局的,慎用;

BindingMethods/BindingMethod

  • BindingMethod用于将属性和非对应的set方法进行匹配,相当于方法重命名;

BindingAdapter/BindingConversion/BindingMethods/BindingMethod

  • 这四类注解用于定义如何将绑定表达式的值绑定到View组件上;通过属性名,View组件类型,绑定表达式值类型来匹配对应的方法进行View更新;
  • 在将绑定表达式的值更新到View组件的解决方案中,优先使用BindingMethods/BindingMethod,相当于将View内置的方法重命名;BindingMethods/BindingMethod不能解决时,再使用BindingAdapter,将自定义属性或者自定义逻辑通过BindingAdapter;如果还不能解决,最后使用BindingConversion,通过转化绑定表达式的值类型来匹配对应方法,慎用;
  • 一个View组件定义一个相关的ViewBinding类,在类声明上添加BindingMethods/BindingMethod注解,类中声明静态方法,静态方法上添加BindingAdapter注解,另外一个单独的BindingConversion类用来声明类型转化方法,添加BindingConversion注解;
  • 对于系统内置的View组件,尽量不要配置对应的绑定属性,使用binding-adapters类库中定义的即可;对于自定义类(非系统内置,非support,androidx中的组件),可以定义一个类来声明该类所有的binding相关的配置;不管是系统内置的View组件还是自定义组件,对于属性名称,最好加一个统一前缀,表明是自定义属性,也方便后期维护;

双向绑定

  • 上面的四类注解是单向绑定需要的,双向绑定是基于单向绑定的;
  • InverseBindingAdapter
    @InverseBindingAdapter("attribute" = attrName, event = attrName + "AttrChange")
    public static Type getAttr(View view, Type old);
    
    • 注解在方法上,用于从View组件获取当前状态;event表示监听事件,需要另外的BindingAdapter(event)方法对View进行监听绑定;
  • InverseBindingMethods/InverseBindingMethod
    InverseBindingMethods({InverseBindingMethod(
        type =android.widget.TextView.class, 
        attribute = "android:text", 
        event = "android:textAttrChanged",
        method = "getText")})
    
    • 和InverseBindingAdapter类似,不需要定义获取View状态的getter方法,同样需要定义BindingAdapter(event)对View进行监听绑定;
  • InverseMethod
    InverseMethod("convertIntToString")
    public static int convertStringToInt(String value);
    
    • 类似于单向绑定中的BindingConversion,逆向转换,但是参数类型,返回类型要和对应的BindingConversion正好相反;

DataBindingComponent

  • 以上注解定义的都是针对全局的方法,如果只是某个XML中需要用到特殊的方法进行数据绑定,那么可以通过一个类实现了DataBindingComponent接口(空接口),并且在获取binding对象时,传入该类的对象即可;
  • 个人不建议采用这种方式,如果某个XML有特殊的数据绑定逻辑,可以通过在可观察数据源上挂监听更新UI(不用DataBinding自动更新部分);

与AAC结合

  • AAC(Android Architecture Component)中很多组件可与DataBinding相结合;
  • LiveData
    • LiveData可当作可观察数据源;
  • ViewModel
    • 通过自定义类继承于ViewModel,并实现Observable接口,当作可观察数据源,ViewModel本身又跨配置更改周期;
  • Lifecycle
    • ViewDataBinding绑定Lifecycle,可实现在非激活状态(onStart之前,onPause之后)不更新UI,激活之后更新UI;

你可能感兴趣的:(Android-DataBinding-使用-高阶)