代码之家  ›  专栏  ›  技术社区  ›  Leo Aso

如何从bindingAdapter访问数据绑定变量

  •  1
  • Leo Aso  · 技术社区  · 6 年前

    例如,假设我的数据绑定xml中有以下变量。

    <layout ...>
        <data>
            <variable name="listener" type="com.xyz.Listener" />
            <!-- and other variables -->
        </data>
        ...
    </layout>
    

    我在我的每个数据绑定布局中都使用这个变量,而且我几乎需要在我的每个数据绑定布局中访问它 @BindingAdapter . 例如,我的绑定适配器基本上是这样的。

    @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 阻止所有绑定适配器。有没有一种方法可以做到这一点,而不必每次都将其作为第二个变量手动传递?

    // 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中的解决方案对我来说也很好。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Leo Aso    6 年前

    在做了更多的研究之后,我发现 DataBindingComponent 接口,它正好解决了我遇到的问题显然,如果使绑定适配器成为实例方法而不是静态方法,编译器将获取您在其中声明的类,并将其作为 数据绑定组件 是的。因此,我制作了绑定适配器实例方法,并通过构造函数注入了所需的变量。

    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)
            }
        }
    }
    

    编译完成后,编译器生成以下接口

    package android.databinding;
    
    public interface DataBindingComponent {
        com.my.package.Binding getBinding();
    }
    

    然后我通过使绑定类扩展这个接口并返回自身来完成这个循环

    class Binding(val listener: Listener) : DataBindingComponent {
        override fun getBinding(): Binding {
            return this
        }
        // all the other stuff
    }
    

    这允许我在膨胀视图时将其作为一个参数传递,因此我甚至不再需要声明 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