Android databinding之数据单向与双向绑定详解与使用(三)
创始人
2024-04-18 09:05:50
0

一、介绍

        通过前面两篇文档,我们大概了解了databinding的工作方式,view的初始化,recycleview的使用。但是这些UI都离不开数据的填充,数据的修饰。

在说到数据绑定,好多开发者平时在工作中也经常听到databinding的数据绑定有简单、单向绑定、双向绑定,玄幻莫测,不敢下手。甚至有些新手听完果然放弃。接下来我会通过代码讲解databinding的数据绑定和使用,包括map、list、和用户自定义类,让复杂的事件简单化,人人都可以掌握好并使用

数据绑定

        数据绑定分为两种,一种是系统支持的,还有一种是databind的数据,接下来我们分梁部分介绍

1、系统默认数据类型

基础数据

String、int、float、double,boolean

    

简单类型,我们直接使用即可

 布局最终引用:

注意:

任何在布局中的value都需要被处理成字符串类型,也就是说boolean或者double不能直接@{double}@{boolean},这种是错误的

正确:

   

错误:

   

注意:一些静态方法可以在布局中直接引用,这个后期会单独介绍

2、ArrayList、HashMap等聚合数据绑定

聚合列的数据,在data下方也是支持的,常用的有以下三种:map、list、sparseArry。

如何使用呢?因为data下方的数据都是要指定泛型的,所以这三种数据都是支持泛型,所以你必须要指定泛型。

泛型格式:

在type里面指定泛型。type格式=ArrayList<String>

这里面有人会不明白<和>是什么意思,

正常格式:ArrayList

databind:ArrayList<String>

所以(<   为<)左括号,(>为>)右括号

    

在这里面,需要注意的是所有key和index最好动态设置,否则不方便业务开展

如何在view中绑定data数据:

        

数据设置:

        var map = HashMap()map.put("name", "map你好")databind.key = "name"databind.map = mapvar list = ArrayList()list.add("list0index")list.add("list1index")
//        databind.list = listvar spar=SparseArray()spar.put(0,"0 value SparseArray")spar.put(1,"1 value SparseArray")spar.put(100,"100 value SparseArray")databind.arry=spardatabind.index = 100

说明:

        如果你的list没有设置,即在databind中为null,即使你设置了key或者index,也不会被引用,如果你设置了data,index会引起数组越界,但是不会抛空指针

二、databind数据介绍

        以上我们讲解的是通过系统数据取完成,但是我们在使用databinding的时候,是想使用他的数据特性,单向绑定、双向绑定。

        我们在上面介绍的数据绑定,都不涉及到,接下来我们要讲解通过databind提供的方式,进行单向绑定和双向绑定

1、单向绑定

什么叫单向绑定:

单向绑定就是data发生改变,会自动通知UI刷新,但是UI内容发生改变后,将不会引用data发生改变。

数据绑定有两种方法,第一种全家桶,第二种,用户自定义

第一种:全家桶模式BaseObservable、Bindable

BaseObservable:提供了数据更新的机制,可以通过notifyPropertyChanged(int field)和notifyChange()来完整数据的更新

Bindable:生成关联字段,形成关联图

如何使用:

1.继承:BaseObservable
2.通过Bindable注解绑定字段,改字段必须为public,否则绑定在get方法上

kotlin:

直接绑定在get方法上

class MySchool : BaseObservable() {@get:Bindablevar name: String = ""set(value) {field = valuenotifyPropertyChanged(BR.name)}}

Java:

public class MySchool extends BaseObservable {private String schoolName="";@Bindablepublic String getSchoolName() {return schoolName;}public void setSchoolName(String schoolName) {this.schoolName = schoolName;notifyPropertyChanged(BR.schoolName);}
}

关于notifyPropertyChanged()和 notifyChange()

notifyPropertyChanged:只刷新指定的字段

notifyChange:刷新对象下所有bindable的字段

注意:

        有人先写set方法,BR无法找到指定的字段,是因为该字段还没有被bindable注释绑定,生成对应的关系图,所以要先bindable,在更新,否则找不到对应的字段

字段更新监听:addOnPropertyChangedCallback

不仅可以单向绑定,我们可以坚定当前绑定的数据对应的字段:

BaseObservable提供了一个addOnPropertyChangedCallback回调,可以在这里设置字段监听
        var detail = MySchool()detail.addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback(){override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
//                TODO("Not yet implemented")}})


2.自定义绑定字段ObservableField

通过上方,我们已知道全家桶配合的使用,但是databinding也提供了基础的绑定方法ObservableField,

BaseObservableField是基础类型,可以通过该类型指定泛型,也可以通过提供的其他数据类型进行绑定ObservableFloat
ObservableBoolean
ObservableInt
ObservableParcelable
ObservableChar
聚合数据
ObservableArrayMap
ObservableArrayList

接下来我们先从最基础的BaseObservableField基础用起

数据源:

class BaseFieldData {lateinit var name: ObservableFieldlateinit var age: ObservableFieldlateinit var god: ObservableField}

class Dog() : Parcelable {lateinit var name: Stringlateinit var hostName: Stringconstructor(parcel: Parcel) : this() {name = parcel.readString()!!hostName = parcel.readString()!!}override fun writeToParcel(parcel: Parcel, flags: Int) {parcel.writeString(name)parcel.writeString(hostName)}override fun describeContents(): Int {return 0}companion object CREATOR : Parcelable.Creator {override fun createFromParcel(parcel: Parcel): Dog {return Dog(parcel)}override fun newArray(size: Int): Array {return arrayOfNulls(size)}}}

实现:

    fun initData() {var name = ObservableField("我的名字")var age = ObservableField(100)var dog = Dog()dog.name = "小黑"dog.hostName = name.get()!!;var isDog = ObservableField(dog)var baseData = BaseFieldData()baseData.age = agebaseData.god = isDogbaseData.name = namedataBind.data = baseDatadataBind.testClick.setOnClickListener {name.set("新名字")var newDog=Dog()newDog.name="我是小白"newDog.hostName=name.get().toString()isDog.set(newDog)}}

通过这样,我们已完成了担心绑定,每次我们只要更新name和age的变量值,UI会自动刷新

每个field通过set()来设置泛型参数,通过get来回去。

为什么我们没手动更新,系统确能自动完成UI的更新?

我们看下ObservableField的set()就可以知道

public void set(T value) {if (value != mValue) {mValue = value;notifyChange();}
}

当我们调用set()的时候,默认也调用的全局刷新。

第二种:采用databind封装好的

分析:

        封装好的ObservableChar已继承了BaseObservableField

public class ObservableChar extends BaseObservableField implements Parcelable, Serializable

所以只是在构造器类指定了内容类型,这样我们在使用的时候,不再需要设置泛型参数。

var size=ObservableDouble(12.0)
      
       dataBind.testClick.setOnClickListener {size.set(123.2)}

这些都很好处理,接下我们将介绍ObservableArrayList和ObservableArrayMap

三、数据集合:

ObservableArrayList和ObservableArrayMap

 介绍一个ObservableArrayMap:

布局中的data:

代码中实现:

        var map = ObservableArrayMap()map.put("name", "zhangshan")dataBind.map = mapdataBind.key = "name"dataBind.testClick.setOnClickListener {map.put("name", "修改过的")}
 

同理,map的put方法如下:

public V put(K k, V v) {V val = super.put(k, v);notifyChange(k);return v;
}

也是调用了全局刷新,同理,ArryList的add方法也是这样:

介绍完以上用法,会发现,这些好像都是单向绑定,什么才是双向绑定?其实很简单

四、双向绑定

        介绍完单向绑定,其实大家已掌握了双向绑定。用周董的话说,全球音乐看话语,中文才是最屌。

双向绑定比单向绑定在view绑定的时候,多一个=号

单向:

双向:

这边采用了

var name = ObservableField("我的名字")

进行测试。

效果图

 总结:

               只要我们掌握了单向绑定,双向绑定自然也会解决。但是,在使用双向的时候需要注意,不同的场景如果存在多处引用,会导致数据错乱。所以,在使用的时候需要格外小心。

        

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...