适用于Android开发者的Databinding自定义view双向绑定
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
前言
本篇默认读者已经对databinding 有过一定的了解,如果不甚了解,可以看看东哥的DataBinding最全使用说明,很多人排斥databinding,但也有人喜欢使用。虽然它有争议,但是不妨碍我们去学习、了解。\ 本篇讲述的是自定义view如何来双向绑定数据,来实现在xml中使用自定义也能达到 app:customvalue="@={userName}"的效果
app:xx="@{userName}" 单向绑定\ app:xx="@={userName}" 双向绑定
引入Databingding
1、第一步 \
引入kapt插件
2、第二步 \
开启databinding(这里有 gradle新版跟旧版的区别,具体是哪个版本,有知道的评论区告诉我)
新版本的gradle
buildFeatures.dataBinding = true
旧版本的gradle
android{
/.../
dataBinding {
enabled = true;
}
}
实现代码
这里提供的实现方法肯定不是最优解,或者说是最好的,但是作为抛砖引玉的小知识,是比较适合的
1、先给大家看一下整个工程的目录
2、首先,新建一个CustomView、里面有一个TextView、EditText来作为演示。 ``` class CustomView(mContext: Context, attributeSet: AttributeSet?) : LinearLayout(mContext, attributeSet) { private var onChangeListener: InverseBindingListener? = null private var onInputChangeListener: InverseBindingListener? = null private var itemInput: EditText? = null private var itemText: TextView? = null var etInput = "" set(value) { val oldValue = field if (value == oldValue) { return; } field = value onInputChangeListener?.onChange() }
var tvValue = ""
set(value) {
val oldValue = field
if (value == oldValue) {
return;
}
field = value
onChangeListener?.onChange()
}
init {
initView(mContext, attributeSet)
}
private fun initView(mContext: Context, attributeSet: AttributeSet?) {
val view = inflate(mContext, R.layout.widget_custom_view, this)
itemInput = view.findViewById(R.id.et_input)
itemText = view.findViewById(R.id.tv_value)
itemText?.setOnClickListener {
tvValue = System.currentTimeMillis().toString()
itemText?.text = tvValue
}
itemInput?.doOnTextChanged { text, start, before, count ->
etInput = text.toString()
}
}
internal fun setOnInputChangeListener(listener: InverseBindingListener) {
if (onInputChangeListener == null) {
this.onInputChangeListener = listener
}
}
internal fun setOnValueChangeListener(listener: InverseBindingListener) {
if (onChangeListener == null) {
this.onChangeListener = listener
}
}
}
widget_custom_view.xml
3、新建一个BindAdapter管理类 DatabindComponent类来管理相关使用,也可以将其中的代码 通过BindMethod的方式写在CustomView中
object DataBindComponent {
@BindingAdapter("itemInput")
@JvmStatic
fun CustomView.setItemInputParams(value: String) {
etInput = value
}
@InverseBindingAdapter(attribute = "itemInput", event = "itemInputAttrChanged")
@JvmStatic
fun getItemInputParams(view: CustomView): String {
return view.etInput
}
@BindingAdapter(value = ["itemInputAttrChanged"], requireAll = false)
@JvmStatic
fun CustomView.itemPutChange(textAttrChanged: InverseBindingListener) {
setOnInputChangeListener(textAttrChanged)
}
@BindingAdapter("itemValue")
@JvmStatic
fun CustomView.setItemValueParams(value: String) {
tvValue = value
}
@InverseBindingAdapter(attribute = "itemValue", event = "itemValueAttrChanged")
@JvmStatic
fun getItemValueParams(view: CustomView): String {
return view.tvValue
}
@BindingAdapter(value = ["itemValueAttrChanged"], requireAll = false)
@JvmStatic
fun CustomView.itemValueChange(textAttrChanged: InverseBindingListener) {
setOnValueChangeListener(textAttrChanged)
}
}
```
4、在xml中添加CustomView,并添加两个ObservableField
总结
没有贴GitHub代码仓库的原因是因为这些示例代码,是通过Moudle的方式写在project中,其中一些Moudle不适合放开。关键代码全都将其放了出来,只有一些使用的代码,通过图片形式展示。如果你刚好有将自定义view双向绑定的需求,以上示例,完全可以帮助到你,如果你有更好的写法,可以在评论区告诉我,让我学习