1.官方文档

  https://developer.android.com/topic/libraries/data-binding/binding-adapters

  https://developer.android.com/topic/libraries/data-binding/two-wa

2.自定义绑定

2.1 系统定义的绑定方法

  假设在绑定布局文件中使用app:aaaaa 的属性,绑定库自动尝试查找方法 setAaaaa(arg)

  • 按app:aaaaa 时传递的参数, 找到参数匹配或兼容的那个方法setAaaaa
  • 不会考虑属性的命名空间
  • 搜索方法时仅使用属性名称和类型
  • 假设类Student包含 setTtttt 这个方法,那么可以直接在布局文件中使用 app:ttttt 这个属性。

2.2 自定义绑定的方法

  • a.重新绑定属性与对应的方法

         @BindingMethods(value = [
    BindingMethod(
    type = ImageView::class,
    attribute = "android:tint",
    method = "setImageTintList")])

上述代码把 android:tint 这个属性绑定到了setImageTintList方法。官方文档中并没有给出这段应该放哪里,放在类里面编译不过,通过官方完整示例中发现它是全局的。

  • b.修改系统已经定义好的方法

             @androidx.databinding.BindingAdapter("android:paddingLeft")
    @JvmStatic
    fun setPaddingLeft(view: View, oldPadding: Int, newPadding: Int) {
    if (oldPadding != newPadding) {
    view.setPadding(,
    view.getPaddingTop(),
    view.getPaddingRight(),
    view.getPaddingBottom())
    }
    }

    重新定义了 android:paddingLeft属性,注意,调用的时候  android:paddingLeft='@{16}' 才匹配这个方法,android:paddingLeft="16dp" 还是系统的那个方法。

   出现冲突时,自定义的绑定方法会替换数据绑定库提供的默认方法.

   重新定义系统已经存在的属性没意义,这个方法要以 '@{16}‘ 这种 方式调用,android:paddingLeft="16dp" 无效

  • c.把多个属性联合在一起,绑定个方法

             @JvmStatic
    @androidx.databinding.BindingAdapter(value = ["imageUrl", "error"], requireAll = false)
    fun loadImage(view: ImageView, url: String, error: Drawable) {
    Picasso.get().load(url).error(error).into(view)
    }

    requireAll = false 的含义是 单独使用imageUrl,error其中一个属性的时候,就绑定这个方法,true就是必需同时使用这两个属性的时候才绑定这个方法。

    使用

    <ImageView
    android:id="@+id/imageView2"
    android:layout_width="64dp"
    android:layout_height="64dp"
    app:error='@{@drawable/error}'
    app:imageUrl='@{"sdfsd.com/fef.ppppjnpng"}'
    />

2.3 类型转换 @BindingConversion

作用:使用这个 注解可以定义一个类型A到类型B在转换函数,函数名的格式为

convertAToB,如 convertStringToData
         @JvmStatic
@androidx.databinding.BindingConversion
fun convertStringToData(name : String) = Data()

3. 双向绑定

3.1 单向的问题

  默认是单向绑定,控件与用户的交互(如输入新的名字,点单选框复选框)不会自动修改对应的绑定数据对象,要在代码里手动处理相应的控件事件,在事件函数里修改数据对象。如:

     val data = Data()
lateinit var binding : Way2Binding
val nameWatcher = object : TextWatcher{
override fun afterTextChanged(p0: Editable?) {
val txt = p0.toString()
data.name = txt
binding.invalidateAll()
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
} fun initBinding(){
binding.data = data
binding.normalEdt.addTextChangedListener(nameWatcher)
}

3.2 使用双向绑定

  使用双向绑定可以简化这个问题,减少相应代码。

  用 @={} 表示可接收属性的数据更改并同时监听用户更新.

       <EditText
...
android:text='@={data.name,default=@string/data_name}'
.../>

  这样当用户在这个EditText上输入新的内容后,直接更新到绑定的数据对象。

  注意: @={} 不可以使用格式化的@string/xx   

3.3 自定义的属性使用双向绑定

a.自定义属性的 setXXX

     @BindingAdapter("dataName")
@JvmStatic fun setDataName(edt : EditText, txt : String){
edt.setText(txt)
}

b.自定义属性的 getXXX

     @InverseBindingAdapter(attribute = "dataName")
@JvmStatic fun getDataName(edt : EditText) : String{
return edt.text.toString()
}

注意:attribute =  不可少,否则编译不过。

c.编写属性变化监听器及想要监听的事件

     @BindingAdapter("dataNameAttrChanged")
@JvmStatic fun setListener(edit : EditText, listener: InverseBindingListener?) {
Log.e("dataNameAttrChanged","txt = ${edit.text.toString()}")
var txt = ""
edit.addTextChangedListener(object : TextWatcher{
override fun afterTextChanged(p0: Editable?) {
Log.e("dataNameAttrChanged","afterTextChanged")
if (txt != p0.toString()){
listener?.onChange()
txt = p0.toString()
}
}
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
})
}
  • InverseBindingListener 是属性变化监听器
  • 这个 EditText 监听的事件是 textChanged

注意:  listener?.onChange() 容易死 循环,要判断下原内容与新内容,不一样才调用这个函数。上述代码中的高亮部分。

d.布局文件中使用

    <EditText  app:dataName='@={data.name}'  ... >

3.4 类型转换的双向绑定

使用类型转换时,也可以使用双向绑定,但是要指定一个反向转换的函数。用 @InverseMethod("转换函数名") 来声明。

 @file:JvmName("Converter")

 package com.example.databind
import androidx.databinding.InverseMethod class A (var name: String) @InverseMethod("a2String")
fun string2a(string: String) : A{
return A(string)
} fun a2String(a : A) : String{
return a.name
}

在布局文件中

    <EditText android:text='@={Converter.a2String(a)}' />

3.5 支持双向绑定的内置属性

控件 属性 绑定适配器所在的类
AdapterView android:selectedItemPosition
android:selection
AdapterViewBindingAdapter
CalendarView android:date CalendarViewBindingAdapter
CompoundButton android:checked CompoundButtonBindingAdapter
DatePicker android:year
android:month
android:day
DatePickerBindingAdapter
NumberPicker android:value NumberPickerBindingAdapter
RadioButton android:checkedButton RadioGroupBindingAdapter
RatingBar android:rating RatingBarBindingAdapter
SeekBar android:progress SeekBarBindingAdapter
TabHost android:currentTab TabHostBindingAdapter
TextView android:text TextViewBindingAdapter
TimePicker android:hour
android:minute
TimePickerBindingAdapte

 

android 数据绑定(6)自定义绑定方法、双向数据绑定的更多相关文章

  1. 【Angular 5】数据绑定、事件绑定和双向绑定

    本文为Angular5的学习笔记,IDE使用Visual Studio Code,内容是关于数据绑定,包括Property Binding.Class Binding.Style Binding. 在 ...

  2. 2-4 Vue中的属性绑定和双向数据绑定

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. Vue学习之vue属性绑定和双向数据绑定

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. angular 双向数据绑定与vue数据的双向数据绑定

    二者都是 MVVM 模式开发的典型代表 angular 是通过脏检测实现,angular 会将 UI 事件,请求事件,settimeout 这类延迟的对象放入到事件监测的脏队列,当数据变化的时候,触发 ...

  5. Angularjs进阶笔记(2)-自定义指令中的数据绑定

    有关自定义指令的scope参数,网上很多文章都在讲这3种绑定方式实现的效果是什么,但几乎没有人讲到底怎么使用,本篇希望聊聊到底怎么用这个话题. 一. 自定义指令 自定义指令,是Angularjs用来实 ...

  6. angularJs初体验,实现双向数据绑定!使用体会:比较爽

    使用初体验:ng 双向数据绑定: 最简单的双向数据绑定:(使用默认模块控制) <body ng-app> <input type="text" ng-model= ...

  7. 组件使用v-model、$listeners、.sync(区别于v-model的双向数据绑定)

    自定义组件 自定义组件的v-model 首先我们先说一下在自定义组件中使用v-model的必要条件 在自定义的组件中要有input(这里我们先不讨论单选复选框) 在自定义组件的模板对象中要有props ...

  8. vue 双向数据绑定的实现学习(一)

    前言:本系列学习笔记从以下几个点展开 什么是双向数据绑定 双向数据绑定的好处 怎么实现双向数据绑定 实现双向数据数据绑定需要哪些知识点 数据劫持 发布订阅模式 先看看我们要实现的目标是什么,如下动图: ...

  9. ng 双向数据绑定

    1.方向1:model->View模型数据绑定到视图 绑定的方式:①双花括号 ②常见的ng指令(ngRepeat ngIf ngShow....) 效果:数据一旦绑定到视图上,随着数据的修改,视 ...

随机推荐

  1. C++的常用输入及其优化以及注意事项

    $\mathcal{P.S:}$ 对于输入方式及其优化有了解的大佬可直接阅读$\mathcal{Part}$ $\mathcal{2}$ 特别鸣谢:@归斋目录: $\mathcal{Part}$ $\ ...

  2. 详解Flask上下文

    上下文是在Flask开发中的一个核心概念,本文将通过阅读源码分享下其原理和实现. Flask系列文章: Flask开发初探 WSGI到底是什么 Flask源码分析一:服务启动 Flask路由内部实现原 ...

  3. win10 安装tensorflow2.0 GPU版本遇到的坑

          背景:我的机器上tensorflow 1.14 & 2.0,这俩版本都有,之前都是用1.14版本,今天试一下2.0尝尝鲜, 结果就掉坑去了 把CUDA10.1 和 cudnn 安装 ...

  4. boost之signal的使用

    文章目录 简介 代码 模板实现: 测试代码 运行结果 简介 boost是C++的一个扩展库,被称为C++准标准库,里面的组件很丰富,并且引用方便,85%的组件只需要引用头文件即可使用. 并且在嵌入式系 ...

  5. 理解HTTP的POST和PUT的区别

    1.HTTP Methods HTTP Methods GET POST PUT HEAD DELETE PATCH OPTIONS GET is used to request data from ...

  6. JS笔记 运算符 函数

    1.运算符 1.位运算符 将数字转换为二进制后进行运算 只做整数运算,如果是小数的话,则去掉小数位再运算 2.位运算 1.按位 与:& 语法:a&b; 2.按位 或| 语法:a|b 任 ...

  7. 15、Java中级进阶 面向对象 继承

    1.何为面向对象 其本质是以建立模型体现出来的抽象思维过程和面向对象的方法(百度百科)是一种编程思维,也是一种思考问题的方式 如何建立面向对象的思维呢?1.先整体,再局部2.先抽象,再具体3.能做什么 ...

  8. JavaIO流,万物皆文件

    引入IO的原因 基本概念: 数据源和流的概念 IO流的概念细分 IO流的体系 IO流在Java中的流对象:inputStream .... Java对象的序列化和反序列化: 1 为什么需要序列化和反序 ...

  9. 准确率、精确率、召回率、F1

    在搭建一个AI模型或者是机器学习模型的时候怎么去评估模型,比如我们前期讲的利用朴素贝叶斯算法做的垃圾邮件分类算法,我们如何取评估它.我们需要一套完整的评估方法对我们的模型进行正确的评估,如果模型效果比 ...

  10. Netty(二):如何处理io请求?

    文接上一篇.上篇讲到netty暴露一个端口出来,acceptor, handler, pipeline, eventloop 都已准备好.但是并没体现其如何处理接入新的网络请求,今天我们就一起来看看吧 ...