为什么在RecyclerView.Adapter的onBindViewHolder中添加一个OnClickListener被认为是不好的做法?

我有一个RecyclerView.Adapter类的下面的代码,它工作正常:

 public class MyAdapter extends RecyclerView.Adapter<MyAdapter.Viewholder> { private List<Information> items; private int itemLayout; public MyAdapter(List<Information> items, int itemLayout){ this.items = items; this.itemLayout = itemLayout; } @Override public Viewholder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false); return new Viewholder(v); } @Override public void onBindViewHolder(Viewholder holder, final int position) { Information item = items.get(position); holder.textView1.setText(item.Title); holder.textView2.setText(item.Date); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(view.getContext(), "Recycle Click" + position, Toast.LENGTH_SHORT).show(); } }); holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { Toast.makeText(v.getContext(), "Recycle Click" + position, Toast.LENGTH_SHORT).show(); return true; } }); } @Override public int getItemCount() { return items.size(); } public class Viewholder extends RecyclerView.ViewHolder { public TextView textView1; public TextView textView2; public Viewholder(View itemView) { super(itemView); textView1=(TextView) itemView.findViewById(R.id.text1); textView2 = (TextView) itemView.findViewById(R.id.date_row); } } } 

不过,我相信在onBindViewHolder方法中实现OnClickListener是不好的做法。 为什么这是不好的做法,什么是更好的select?

在ViewHolder中处理你的点击逻辑更好的原因是它允许更明确的点击监听器。 正如在Commonsware书中所表示的那样:

长久以来,ListView行中的可点击小部件(如RatingBar)与行本身的点击事件相冲突。 获取可点击的行,同时也可以点击行内容,有时会有点棘手。 使用RecyclerView,您可以更加明确地控制如何处理这类事情……因为您是设置所有点击式处理逻辑的人。

通过使用ViewHolder模型,您可以比之前在ListView中的RecyclerView中的点击处理获得很多好处。 我在博客文章中比较了这些差异 – http://androidessence.com/recyclerview-vs-listview/

至于为什么它在ViewHolder而不是在onBindViewHolder()onBindViewHolder() ,这是因为onBindViewHolder()被调用的每一个项目和设置点击监听器是一个不必要的select重复,当你可以在你的ViewHolder构造函数调用一次。 然后,如果您的点击响应取决于所点击的项目的位置,您可以简单地从ViewHolder中调用getAdapterPosition() 。 这是我给出的另一个答案,演示了如何在ViewHolder类中使用OnClickListener。

onCreateViewHolder()方法将被称为每个viewType需要ViewHolder的前几次。 onBindViewHolder()方法将在每次新项目滚动到视图或数据更改时调用。 你想避免在onBindViewHolder()任何昂贵的操作,因为它可以减慢你的滚动。 这在onCreateViewHolder()不太受关注。 因此,在onCreateViewHolder()创buildOnClickListener的东西通常会更好,这样每个ViewHolder对象只会发生一次。 您可以在侦听器中调用getLayoutPosition()以获取当前位置,而不是将position参数提供给onBindViewHolder()

每次将视图绑定到刚刚没有看到的对象时,都会调用onBindViewHolder方法。 每次你会添加新的听众。 你应该这样做

 @Override public Viewholder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false); final ViewHolder holder = new ViewHolder(v); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d(TAG, "position = " + holder.getAdapterPosition()); } }); return new Viewholder(v); }