如何使用数据绑定在 RecyclerView 中添加 onClickListener

How to add an onClickListener in RecyclerView using data binding

我刚开始使用 databinding,现在我被困在 数据绑定 方式 recyclerView 中实现点击监听器。 我让它像这样工作:

  @NonNull
    @Override
    public BookViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        ItemBookCoversBinding binding = ItemBookCoversBinding.inflate(LayoutInflater.from(context), parent, false);
        final BookViewHolder bookViewHolder = new BookViewHolder(binding);
        bookViewHolder.binding.bookDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.deleteCover(bookViewHolder.getAdapterPosition());
            }
        });
        bookViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.changeCover(bookViewHolder.getAdapterPosition());
            }
        });
        return bookViewHolder;
    }

确实可以正常工作,但我没有将 databinding 用于 clickListener。 我试过像这样在我的布局中添加一个可变位置:

   <data>

        <variable
            name="position"
            type="int" />

        <variable
            name="listener"
            type="....interfaces.Listener" />


    </data>
    <ImageView
        android:id="@+id/book_cover"
        coverImage="@{bookImages.storageRef}"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_green_dark"
        android:onClick="@{() -> listener.changeCover(position)}"
        android:src="@drawable/placeholder" />

并且在适配器中的 onCreateViewHolder 中:

bookViewHolder.binding.setVariable(BR.position, bookViewHolder.getAdapterPosition());

或者这个:

 binding.setPosition(bookViewHolder.getAdapterPosition());

onClick 在两种情况下都按预期工作,但 bookViewHolder.getAdapterPosition() returns -1,NO_POSITION

我在这里错过了什么? 在 RecyclerView 中实现 databinding onClickListener 的最佳方法是什么?

我已经有了一些有用的东西,但不是 databinding 的方法。

它不起作用,因为您在视图创建时分配了变量。目前您的 ViewHolder 没有 adapterPositions。我不知道它们究竟是如何工作的,但每当我尝试在点击监听器之外使用它时,它总是返回 -1。它们此时没有附加到 RecyclerView,因此如果没有一些异步工作或 layoutChangeListeners 就无法获得它,并且它可能在 onCreateViewHolder

中始终为 -1

解决方法是从其他地方获取您的 ViewHolder 位置。在覆盖 getItemViewType(int pos) 方法后,您可以使用 viewType 变量获得此信息:

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    @NonNull
    @Override
    public PlaylistViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewTypeButActuallyItIsPosition) {
        ...
        binding.setPosition(viewTypeButActuallyItIsPosition);
        ...
    }

编辑

您使用这种方法可能面临的一个问题(在我看来您可能会遇到)是当您的 ViewHolders 被回收时 ImageViews 将设置错误的位置,因为 onBindViewHolder 方法将在不调用 onCreateViewHolder 的情况下被调用,UI 将被更改但绑定变量将保持不变,因此正确的方法是在 onBindViewHolder 方法中分配此位置。这意味着您应该将绑定保留在 ViewHolder class 中并将其保留在 public 中,以便您可以在 onBindViewHolder

中访问它
    @Override
    public void onBindViewHolder(@NonNull YourViewHolder holder, int i) {
        ...
        holder.binding.setPosition(i);
    }

似乎当您在适配器中执行 data binding 时,您想要设置将触发 clickListener 的变量以及您选择填充每个项目的数据绑定方法。 因为它是一个变量,而不是一个方法。

在适配器中实施点击侦听器是开发人员的样板代码。

  • 您应该在适配器中创建接口并从 activity/Fragment 实现它,并从 xml 文件调用它,因为您希望与数据绑定集成。

Here is the link to implement the click listeners best way.