假设我在数据绑定(bind)的XML中具有以下变量。
<layout ...>
<data>
<variable name="listener" type="com.xyz.Listener" />
<!-- and other variables -->
</data>
...
</layout>
我在每个数据绑定(bind)布局中都使用了此变量,并且需要在
@BindingAdapter
的几乎每个布局中使用它。例如,我的绑定(bind)适配器通常看起来像这样。@BindingAdapter("board")
fun setBoard(view: TextView, board: Board) {
view.setText(board.name)
view.setOnClickListener {
listener.onBoardClicked(board)
}
}
@BindingAdapter("topic")
fun setTopic(view: TextView, topic: Topic) {
view.setText(topic.name)
view.setOnClickListener {
listener.onTopicClicked(topic)
}
}
// and a few others like that
我像这样使用它们
<TextView ... app:board="@{board}" ... />
<TextView ... app:topic="@{topic}" ... />
我这里需要的是一种将
listener
块中声明的data
变量访问所有我的绑定(bind)适配器的方法。有没有一种方法可以做到,而不必每次都手动将其作为第二个变量传递?// I know I can do this - looking for an alternative
@BindingAdapter({"board", "listener"})
fun setBoard(view: TextView, board: Board, listener: Listener) {
view.setText(board.name)
view.setOnClickListener {
listener.onBoardClicked(board)
}
}
我在这里使用Kotlin,但是Java的解决方案对我来说也很好。
最佳答案
经过更多研究之后,我才发现了DataBindingComponent
接口(interface),它恰好解决了我遇到的问题。显然,如果使绑定(bind)适配器实例方法而不是静态方法,则编译器将采用您在其中声明的类,并将其添加为DataBindingComponent
的属性。因此,我制作了绑定(bind)适配器实例方法,并通过构造函数注入(inject)了想要的变量。
class Binding(val listener: Listener) {
@BindingAdapter("board")
fun setBoard(view: TextView, board: Board) {
view.setText(board.name)
view.setOnClickListener {
listener.onBoardClicked(board)
}
}
@BindingAdapter("topic")
fun setTopic(view: TextView, topic: Topic) {
view.setText(topic.name)
view.setOnClickListener {
listener.onTopicClicked(topic)
}
}
}
构建完成后,编译器生成以下接口(interface)
package android.databinding;
public interface DataBindingComponent {
com.my.package.Binding getBinding();
}
然后,我通过使绑定(bind)类扩展此接口(interface)并返回自身来完成循环
class Binding(val listener: Listener) : DataBindingComponent {
override fun getBinding(): Binding {
return this
}
// all the other stuff
}
这使我可以在扩展 View 时将其作为参数传递,因此,我什至不必将
listener
声明为XML变量。我可以声明Binding
实例val bindingComponent = Binding(object : Listener {
// implement listener methods here
})
并在放大布局时通过
// now I can use it in activities
DataBindingUtil.setContentView<MyActivityBinding>(
this, R.layout.my_activity, bindingComponent)
// ...or in fragments
DataBindingUtil.inflate<MyFragmentBinding>(
inflater, R.layout.my_fragment, parent, false)
// ...or any other place DataBindingUtil allows