为什么在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); }