【问题标题】:How to add an onClickListener in RecyclerView using data binding如何使用数据绑定在 RecyclerView 中添加 onClickListener
【发布时间】:2020-04-05 00:40:12
【问题描述】:

我刚开始使用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() 返回 -1,NO_POSITION

我在这里缺少什么? 在RecyclerView 中实现databinding onClickListener 的最佳方法是什么?

我已经有了一些可行的方法,但不是databinding 方式。

【问题讨论】:

    标签: android android-recyclerview fragment onclicklistener


    【解决方案1】:

    它不起作用,因为您在视图创建时分配变量。此时您的ViewHolders 没有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 类中并保持公开,以便您可以在 onBindViewHolder 中访问它

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

    【讨论】:

    • 有一个来自 Yigit Boyar 的演讲,他解释说点击监听器应该附加到onCreateViewHolder()。此外,当前工作的传统方法.setonclicklistener() 不会返回-1
    • 是的,点击侦听器必须始终附加在onCreateViewHolderViewHolder 的构造函数中,因为它是繁重的操作,必须在视图创建时执行。但问题是,setOnClickListener 是异步回调,当它被调用(用户点击它)时,它总是附加到适配器上,ViewHolder 已经有了它的适配器位置。但是在您的代码 sn-p 中,您尝试在视图创建时分配它,此时它始终为 -1。 onBindViewHolder 是您在附加视图之前唯一可以拥有它的地方。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-31
        • 2022-08-19
        • 1970-01-01
        • 2021-01-04
        • 2020-10-07
        • 1970-01-01
        • 1970-01-01
        • 2018-06-12
        相关资源
        最近更新 更多