You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确获取RecyclerView Holder数据并通过Intent传递(优化监听写法)

解决RecyclerView中onBindViewHolder内设置监听器的不良实践问题

你提到的在onBindViewHolder里设置点击监听器确实是需要优化的点——每次RecyclerView复用Item时都会创建新的监听器实例,既浪费内存也不符合ViewHolder的复用设计理念。下面是修改后的完整AdapterDoctrines代码,同时解决了获取数据传递Intent的问题:

public class AdapterDoctrines extends RecyclerView.Adapter<AdapterDoctrines.DoctrinesHolder> {
    private Context mContext;
    public List<ModelGreatDoctrines> doctrines;

    public AdapterDoctrines(Context mContext, List<ModelGreatDoctrines> doctrines) {
        this.mContext = mContext;
        this.doctrines = doctrines;
    }

    @NonNull
    @Override
    public DoctrinesHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View viewDoctrineCard = LayoutInflater.from(mContext)
                .inflate(R.layout.card_doctrine, parent, false);
        return new DoctrinesHolder(viewDoctrineCard);
    }

    @Override
    public void onBindViewHolder(@NonNull DoctrinesHolder holder, int position) {
        // 只负责绑定数据,监听器已经在ViewHolder里初始化好了
        ModelGreatDoctrines currentDoctrine = doctrines.get(position);
        holder.textViewTitle.setText(currentDoctrine.doctrineTitle);
        holder.textViewDesc.setText(currentDoctrine.doctrineSummary);
        // 如果有其他数据需要绑定,继续在这里添加
    }

    @Override
    public int getItemCount() {
        return doctrines.size();
    }

    class DoctrinesHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        CardView mCardView;
        AppCompatTextView textViewTitle;
        AppCompatTextView textViewDesc;
        AppCompatButton buttonRead;
        AppCompatButton buttonDownload;

        public DoctrinesHolder(View itemView) {
            super(itemView);
            mCardView = itemView.findViewById(R.id.card_great_doctrine);
            textViewTitle = itemView.findViewById(R.id.card_doctrine_title);
            textViewDesc = itemView.findViewById(R.id.card_doctrine_desc);
            buttonRead = itemView.findViewById(R.id.card_doctrine_read);
            buttonDownload = itemView.findViewById(R.id.card_doctrine_download);

            // 在这里一次性设置监听器,ViewHolder复用的时候不会重复创建
            mCardView.setOnClickListener(this);
            buttonRead.setOnClickListener(this);
            buttonDownload.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            int id = view.getId();
            // 获取当前Item对应的数据位置
            int currentPosition = getBindingAdapterPosition();
            // 检查位置是否有效(避免ViewHolder复用导致的位置错误)
            if (currentPosition == RecyclerView.NO_POSITION) return;

            ModelGreatDoctrines currentDoctrine = doctrines.get(currentPosition);

            switch (id) {
                case R.id.card_great_doctrine:
                    // 处理卡片点击逻辑
                    break;
                case R.id.card_doctrine_read:
                    // 跳转页面并传递数据
                    Intent intent = new Intent(mContext, ViewerDoctrineActivity.class);
                    // 传递需要的数据,比如标题、摘要等
                    intent.putExtra("DOCTRINE_TITLE", currentDoctrine.doctrineTitle);
                    intent.putExtra("DOCTRINE_SUMMARY", currentDoctrine.doctrineSummary);
                    // 可以根据你的Model类添加更多需要传递的字段
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    mContext.startActivity(intent);
                    break;
                case R.id.card_doctrine_download:
                    // 处理下载逻辑,同样可以使用currentDoctrine获取下载所需数据
                    // PERFORM DOWNLOAD USING DOWNLOAD MANAGER
                    break;
            }
        }
    }
}

关键优化点说明:

  • 监听器初始化移到ViewHolder构造方法:只在ViewHolder创建时设置一次监听器,复用Item时不会重复创建,节省内存开销。
  • 通过getBindingAdapterPosition()获取当前位置:替代直接用position参数,避免ViewHolder复用导致的位置错误(如果用旧版本RecyclerView,也可以用getAdapterPosition())。
  • 数据绑定与事件处理分离:onBindViewHolder只负责数据填充,事件逻辑全部放在ViewHolder的onClick方法里,代码结构更清晰。
  • 直接在点击事件中获取数据:通过当前位置从数据源doctrines中拿到对应的数据对象,再传递给Intent,不需要依赖ViewHolder中的View来获取数据(避免View复用导致的数据不一致)。

内容的提问来源于stack exchange,提问作者RoCkDevstack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:00:52