ViewHolder 中的 onClick 无权访问适配器中的单击项目

Posted

技术标签:

【中文标题】ViewHolder 中的 onClick 无权访问适配器中的单击项目【英文标题】:onClick inside ViewHolder doesn't have access to clicked item in adapter 【发布时间】:2017-01-22 09:37:31 【问题描述】:

1) 问题

我想在 CardView 内的 2 个按钮上设置 2 个侦听器。我需要知道选择了哪个项目。我将 CardView 与 RecyclerView 和 FirebaseRecyclerAdapter (RecyclerView.Adapter) 一起使用

2) 旧情况

我在 FirebaseRecyclerAdapter 的 populateViewHolder() 中创建了监听器,如下所示:

@Override
protected void populateViewHolder(final ItemViewHolder viewHolder, final Item model, final int position) 

    viewHolder.firstButton.setOnClickListener(new View.OnClickListener() 
        Item selectedItem = getItem(position);
        //do something for the item selected
    


这很好用!

3) 我想做的事

在 ViewHolder 类中设置监听器(在他自己的文件中定义)并对选中的 ITEM 做一些事情

我想在 ViewHolder 类中设置监听器,因为相同的 ViewHolder 用于不同的适配器,我认为将监听器的行为只定义在一个地方是一种更好的方法。

我是这样做的:

public class ItemViewHolder extends RecyclerView.ViewHolder 

    public CardView cardView;
    public TextView itemText;
    public ImageView itemFirstButton;
    public ImageView itemSecondButton;

    public ItemViewHolder(View itemView) 
        super(itemView);
        cardView = (CardView)itemView.findViewById(R.id.item_card_view);
        itemText = (TextView)itemView.findViewById(R.id.item_text);
        itemFirstButton = (ImageView)itemView.findViewById(R.id.ic_first_action);
        itemSecondButton = (ImageView)itemView.findViewById(R.id.ic_second_action);

        itemFirstButton.setOnClickListener(firstListener);
        itemSecondButton.setOnClickListener(secondListener);
    


    private View.OnClickListener firstLinstener = new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            int position =  getAdapterPosition();
        
    ;

    private View.OnClickListener secondListener = new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            int position = getAdapterPosition();
        
    ;

在侦听器内部,我无法获得有关该项目的任何参考,只有位置...

我的印象是我必须为侦听器声明一个接口并传递给适配器,但我不知道如何。

在视图中声明侦听器是否仍然有意义,或者我将它们作为旧解决方案保留在适配器中?

【问题讨论】:

没有。当您需要来自适配器的东西时,将侦听器放在 ViewHolder 中对我来说没有意义。由于视图在滚动过程中不断被销毁和重新创建,因此您需要在 onBind 期间对其进行定义。如果你的监听器做了一些通用的事情并且不依赖于任何适配器数据,那么将它放在 viewHolder 中是有意义的。 嗨,Panther,我的听众做了一些依赖于项目的事情(例如单击我想共享项目数据的按钮)。共享操作对于使用相同 ViewHolder 的 2 个不同适配器具有相同的行为。因此,如果我很好理解,您建议将侦听器保留在适配器内... 是的,我建议您将监听器保留在适配器内。但是,由于您提到操作是相同的,我相信您正在尝试找到一个 DRY 解决方案。在您的情况下,我会做的是编写一个通用函数来执行所有共享。侦听器只是一个代理,它将使用适当的数据调用共享操作。 【参考方案1】:

如果你想告诉适配器你的位置,只需通过 ViewHolder 构造函数传递一些接口。 要么 以前的方式。

关键是您要将职位委派给谁。

【讨论】:

【参考方案2】:

是的,使用界面是个好习惯。创建一个类似

的界面
public interface OnClick 
    void getItem(int item);

然后setOnClicklistner就好了

itemViewHolder. itemText.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                OnClick onClick = (OnClick)context;
                onClick.getItem(position);
            
        );

然后在您的活动中实现该方法。从这里你得到位置。然后通过使用位置从数组中获取元素。

【讨论】:

您好,感谢您的回答……抱歉,我不太清楚该怎么做。我必须在适配器上设置监听器吗?假设我想在 ViewHolder 中定义一个侦听器,该侦听器能够实现共享操作以共享所选项目数据(因此应在 ViewHolder 中定义 onClick 行为)。如何将项目从适配器传递到 ViewHolder?

以上是关于ViewHolder 中的 onClick 无权访问适配器中的单击项目的主要内容,如果未能解决你的问题,请参考以下文章

在Android Kotlin中,将onclick事件传递给viewholder的正确方法是啥?

在 RecyclerView 适配器中初始化 viewHolder 时出错

如何在 Kotlin 中为 Android 的 RecyclerView 适配器初始化 viewHolder

如何使用 OnClick 事件调用 JS 函数

行 onClick 影响其他行

Recyclerview ViewHolder中的TextView - OnClickListener