在Android Studio 2.1 Preview 3之后,官方开始支持双向绑定了。
创新互联公司专注于辰溪企业网站建设,响应式网站,成都做商城网站。辰溪网站建设公司,为辰溪等地区提供建站服务。全流程按需设计,专业设计,全程项目跟踪,创新互联公司专业和态度为您提供的服务
可惜目前Google并没有在Data Binding指南里面加入这个教程,并且在整个互联网之中只有 这篇文章 介绍了如何使用反向绑定。
在阅读一下文章之前,我假设你已经知道如何正向绑定。
在正向绑定中,我们在Layout里面的绑定表达式是这样的:
当user.name的数据改动时,我们的TextView都会同步改变文字。
现在假设一种情况,当你更换成EditText时,如果你的用户名User.name已经绑定到 EditText 中,当用户输入文字的时候,你原来的user.name数据并没有同步改动,因此我们需要修改成:
看出微小的差别了吗?对,就是"@{}"改成了"@={}",是不是很简单?
同样你也可以在别的View上引用属性:
当CheckBox的状态发生改变的时候,ImageView也会同时发生改变。在复杂情况下,这个特性没什么卵用,因为逻辑部分我们是不建议写在XML中。
开启双向绑定,需要在项目的build.gradle中设置:
同样,你需要在你Module的build.gradle中设置:
我们刚才的例子里面只显示了系统自带的应用,那么如果是自定义控件,或者是我们更细颗粒度的 Observable 呢?等下就揭晓如何自定义自己的双向绑定,我们来看看目前Android支持的控件:
设想一下我们使用了下拉刷新 SwipeRefreshLayout 控件,这个时候我们希望在加载数据的时候能控制refreshing的状态,所以我们加入了 ObservableBoolean 的变量swipeRefreshViewRefreshing来正向绑定数据,并且能够在用户手动下拉刷新的时候同步更新swipeRefreshViewRefreshing数据:
接下来我们需要告诉框架,我们需要将 SwipeRefreshLayout 的isRefreshing的值反向绑定到 swipeRefreshViewRefreshing :
这是一种简单的定义,其中event和method都不是必须的,因为系统会自动生成,写出来是为了更好地了解如何绑定的,可以参考官方文档 InverseBindingMethod 。
当然你也可以使用另外一种写法,并且如果你的值并不是直接对应 Observable 的值的时候,就可以在这里进行转换:
上面的event同样也不是必须的。以上的定义都是为了让我们能够在布局文件中使用"@={}"这个双向绑定的特性。接下来你需要告诉框架如何处理refreshingAttrChanged事件,就像处理一般的监听事件一样:
一般情况下,我们都需要设置正常的OnRefreshListener,所以我们可以合并写成:
现在我们终于可以使用双向绑定的技术啦。但是要注意,需要设置 requireAll = false ,否则系统将识别不了refreshingAttrChanged属性,前文提到的文章例子里并没有设置这个。
在ViewModel中,我们的数据是这样的:
在布局文件中是这样设置的:
最后我们还有一个小问题,就是双向绑定有可能会出现死循环,因为当你通过Listener反向设置数据时,数据也会再次发送事件给View。所以我们需要在设置一下避免死循环:
这样就没问题啦。
CoAP(Constrained Application Protocol)也叫做“受限应用协议”是一种在物联网世界的类web协议,它的详细规范定义在 RFC 7252。参考如下两篇博客学习更多关于CoAP信息。
CoAP简介
CoAP协议使用
Andlink是中国移动提出的一套设备接入和管理的协议,实现方式复杂,在此不做过多描述,该协议可进行设备与网关之间通信,从而实现设备绑定和管控。Andlink采用CoAP或MQTT作为通信协议。
1、APP进入网关绑定页面,确认wifi是否开启(如果未开启,提示用户开启wifi并绑定到与网关相同wifi下
2、进入网关绑定页后,APP在局域网中每隔1秒发送/qlink/searchdevice的广播,同时调用全屋平台startBind接口
3、收到网关反馈,确认产品id与网关一致后,向网关发送配网信息,注意这里"CGW"地址随开发测试环境不同改变
4、网关入网成功后,会发送/qlink/success的广播消息
5、网关绑定成功后,会发送/qlink/regist的广播消息,包含设备ID
6、后台给APP推送一条网关绑定成功的消息,接收到该消息后,跳出绑定成功界面
最近封装了几个View,都和生命周期有关,比如BannerView、和我们公司的ARView,那他们的生命周期怎么绑定呢?刚开始我是直接告诉别人,你自己在哪个activity使用的,就在哪个activity绑定,结果使用的时候被甲方对接人员打回来说这是低级处理方式,wtm这暴脾气,谁tm低级了,但是没办法别人是甲方只能听他的,直接将生命周期的绑定绑在view里面。下面就介绍几个常用的生命周期绑定。
Application.ActivityLifecycleCallbacks是Android自带的生命周期绑定接口,他有注册与解除方法,当我们进入一个activity的时候就可以注册绑定他了。
简单demo。比如我们要讲一个自定义的View绑定生命周期。
1、先定义一个Application.ActivityLifecycleCallbacks的实现类,为什么这样呢?是因为用户可以要什么选什么,就不用被迫每次都实现全部。
2、定义一个测试用的view,在构造方法绑定注册生命周期,
((Activity)context).getApplication().registerActivityLifecycleCallbacks(lifecycleCallbacks);这句话是注册生命周期当然他也对应了一个((Activity)context).getApplication().unregisterActivityLifecycleCallbacks(lifecycleCallbacks);解绑方法。
在ActivityLifecycleCallbacks 的实现中判断了返回的activity是否为这个view所在的acrivity因为很多activity都会走这个方法,如果不做判断,其他activity的生命周期也会影响这个view,所以加判断是个好习惯。
这次我们模拟一个普通类绑定生命周期这个类名叫Test,哈哈,是不是很高大上?但是写Test类之前先定义我们要绑定的生命周期接口LifecycleListener
这里我们监听下常用的onResume、onPause、onDestroy。
然后是Test类
然后写LifecycleDetector,尝试将test类的实例与fragment绑定
定义没有布局的fragment实例
然后保存fragment和Requestmanager关系
还有一个遗漏的接口
上面这些完成后,就可以使用了,我们随便搞个activity试试名字就叫LeftDemoActivity非常好听了有没有!
当你运行起来的时候,就是成功的时候。
有个东西忘啦,getSnapshot是做保存的,直接把源码拿过来的。
还有其他的方法我没试过,但是这样的生命周期绑定可以解决挺多bug的,玩过哔哩哔哩的应该会遇到他们的一个bug,就是进入一个视频播放页,然后还没加载完成就息屏,他这个时候异步回调回来视频数据了就会在息屏或锁屏界面播出音频来,这是典型的生命周期bug,我遇到过几次了,如果加入这个绑定轻松就能解决问题啦。