为什么RecyclerView没有onItemClickListener()?

我正在探索RecyclerView,我惊讶地发现RecyclerView没有onItemClickListener()

我有两个问题。

主要问题

我想知道为什么谷歌删除了onItemClickListener()

是性能问题还是别的什么?

次要问题

我通过在我的RecyclerView.Adapter中写入onClick来解决我的问题:

public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public TextView txtViewTitle;public ImageView imgViewIcon;
public ViewHolder(View itemLayoutView) {super(itemLayoutView);txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);}
@Overridepublic void onClick(View v) {
}}

这样可以吗/有更好的方法吗?

434477 次浏览

tl; dr 2016使用RxJava和PublishSubject为点击公开Observable。

public class ReactiveAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {String[] mDataset = { "Data", "In", "Adapter" };
private final PublishSubject<String> onClickSubject = PublishSubject.create();
@Overridepublic void onBindViewHolder(final ViewHolder holder, int position) {final String element = mDataset[position];
holder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {onClickSubject.onNext(element);}});}
public Observable<String> getPositionClicks(){return onClickSubject.asObservable();}}

原文:

自从引入ListView以来,onItemClickListener一直存在问题。当您有任何内部元素的单击侦听器时,回调不会被触发,但它没有得到通知或良好记录(如果有的话),因此存在很多混淆和SO问题。

鉴于RecyclerView更进一步,没有行/列的概念,而是任意布置的子级数量,他们已经将onClick委托给它们中的每一个,或者程序员实现。

不要将Recyclerview视为ListView:1的替代品,而是将其视为复杂用例的更灵活的组件。正如你所说,你的解决方案是谷歌对你的期望。现在你有了一个适配器,可以将onClick委托给构造函数传递的接口,这是ListViewRecyclerview的正确模式。

public static class ViewHolder extends RecyclerView.ViewHolder implements OnClickListener {
public TextView txtViewTitle;public ImageView imgViewIcon;public IMyViewHolderClicks mListener;
public ViewHolder(View itemLayoutView, IMyViewHolderClicks listener) {super(itemLayoutView);mListener = listener;txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);imgViewIcon.setOnClickListener(this);itemLayoutView.setOnClickListener(this);}
@Overridepublic void onClick(View v) {if (v instanceof ImageView){mListener.onTomato((ImageView)v);} else {mListener.onPotato(v);}}
public static interface IMyViewHolderClicks {public void onPotato(View caller);public void onTomato(ImageView callerImage);}
}

然后在你的适配器上

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
String[] mDataset = { "Data" };
@Overridepublic MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.my_layout, parent, false);
MyAdapter.ViewHolder vh = new ViewHolder(v, new MyAdapter.ViewHolder.IMyViewHolderClicks() {public void onPotato(View caller) { Log.d("VEGETABLES", "Poh-tah-tos"); };public void onTomato(ImageView callerImage) { Log.d("VEGETABLES", "To-m8-tohs"); }});return vh;}
// Replace the contents of a view (invoked by the layout manager)@Overridepublic void onBindViewHolder(ViewHolder holder, int position) {// Get element from your dataset at this position// Replace the contents of the view with that element// Clear the ones that won't be usedholder.txtViewTitle.setText(mDataset[position]);}
// Return the size of your dataset (invoked by the layout manager)@Overridepublic int getItemCount() {return mDataset.length;}...

现在查看最后一段代码:onCreateViewHolder(ViewGroup parent, int viewType)签名已经建议了不同的视图类型。对于它们中的每一个,你也需要一个不同的查看窗口,随后它们中的每一个都可以有一组不同的点击。或者你可以创建一个通用的查看窗口,它接受任何视图和一个onClickListener并相应地应用。或者将一个级别委托给编排器,这样多个片段/活动具有相同的列表,但具有不同的点击行为。同样,所有的灵活性都在你这边。

这是一个非常需要的组件,与我们迄今为止对ListView的内部实现和改进相当接近。谷歌终于承认了这一点,这很好。

>RecyclerView与Listview有何不同?

一个不同之处是,有LayoutManager类与回收视图,你可以管理你的RecyclerView喜欢-

水平或垂直滚动LinearLayoutManager

网格布局GridLayoutManager

交错网格布局StaggeredGridLayoutManager

就像水平滚动的回收站一样-

LinearLayoutManager llm = new LinearLayoutManager(context);llm.setOrientation(LinearLayoutManager.HORIZONTAL);recyclerView.setLayoutManager(llm);

我喜欢这种方式,我正在使用它

里面

public Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)

View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_image_and_text, parent, false);v.setOnClickListener(new MyOnClickListener());

在任何你想要的地方创建这个类

class MyOnClickListener implements View.OnClickListener {@Overridepublic void onClick(View v) {int itemPosition = recyclerView.indexOfChild(v);Log.e("Clicked and Position is ",String.valueOf(itemPosition));}}

我以前读过,有一个更好的方法,但我喜欢这种方式很简单,不复杂。

如何把它放在一起的例子…

  • onClick()处理
  • 光标-回收器视图
  • ViewHolder类型

    public class OrderListCursorAdapter extends CursorRecyclerViewAdapter<OrderListCursorAdapter.ViewHolder> {
    private static final String TAG = OrderListCursorAdapter.class.getSimpleName();private static final int ID_VIEW_HOLDER_ACTUAL = 0;private static final int ID_VIEW_HOLDER = 1;
    public OrderListCursorAdapter(Context context, Cursor cursor) {super(context, cursor);}
    public static class ViewHolderActual extends ViewHolder {private static final String TAG = ViewHolderActual.class.getSimpleName();protected IViewHolderClick listener;protected Button button;
    public ViewHolderActual(View v, IViewHolderClick listener) {super(v, listener);this.listener = listener;button = (Button) v.findViewById(R.id.orderList_item_button);button.setOnClickListener(this);}
    public void initFromData(OrderData data) {Log.d(TAG, "><initFromData(data=" + data + ")");orderId = data.getId();vAddressStart.setText(data.getAddressStart());vAddressEnd.setText(data.getAddressEnd());}
    @Overridepublic void onClick(View view) {if (view instanceof Button) {listener.onButtonClick((Button) view, getPosition(), this);} else {super.onClick(view);}}
    public interface IViewHolderClick extends ViewHolder.IViewHolderClick {public void onButtonClick(Button button, int position, ViewHolder viewHolder);}}
    public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {private static final String TAG = ViewHolder.class.getSimpleName();protected long orderId;protected IViewHolderClick listener;protected TextView vAddressStart;protected TextView vAddressEnd;protected TextView vStatus;
    public ViewHolder(View v, IViewHolderClick listener) {super(v);this.listener = listener;v.setOnClickListener(this);
    vAddressStart = (TextView) v.findViewById(R.id.addressStart);vAddressEnd = (TextView) v.findViewById(R.id.addressEnd);vStatus = (TextView) v.findViewById(R.id.status);}
    public void initFromData(OrderData data) {Log.d(TAG, "><initFromData(data=" + data + ")");orderId = data.getId();vAddressStart.setText(data.getAddressStart());vAddressEnd.setText(data.getAddressEnd());}
    public long getOrderId() {return orderId;}
    @Overridepublic void onClick(View view) {listener.onCardClick(view, getPosition(), this);}
    public interface IViewHolderClick {public void onCardClick(View view, int position, ViewHolder viewHolder);}}
    @Overridepublic int getItemViewType(int position) {return position == 0 ? ID_VIEW_HOLDER_ACTUAL : ID_VIEW_HOLDER;}
    @Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {Log.d(TAG, ">>onCreateViewHolder(parent=" + parent + ", viewType=" + viewType + ")");
    ViewHolder result;
    switch (viewType) {case ID_VIEW_HOLDER_ACTUAL: {View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_layout_actual, parent, false);result = new ViewHolderActual(itemView, new ViewHolderActual.IViewHolderClick() {@Overridepublic void onCardClick(View view, int position, ViewHolder viewHolder) {Log.d(TAG, "><onCardClick(view=" + view + ", position=" + position + ", viewHolder=" + viewHolder + ")");Intent intent = new Intent(view.getContext(), OrderDetailActivity.class);intent.putExtra(OrderDetailActivity.ARG_ORDER_ID, viewHolder.getOrderId());view.getContext().startActivity(intent);}
    @Overridepublic void onButtonClick(Button button, int position, ViewHolder viewHolder) {Log.d(TAG, "><onButtonClick(button=" + button + ", position=" + position + ", viewHolder=" + viewHolder + ")");Intent intent = new Intent(button.getContext(), OrderMapActivity.class);intent.putExtra(OrderMapActivity.ARG_ORDER_ID, viewHolder.getOrderId());button.getContext().startActivity(intent);}});break;}case ID_VIEW_HOLDER:default: {View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_layout, parent, false);result = new ViewHolder(itemView, new ViewHolder.IViewHolderClick() {@Overridepublic void onCardClick(View view, int position, ViewHolder viewHolder) {Log.d(TAG, "><onCardClick(view=" + view + ", position=" + position + ", viewHolder=" + viewHolder + ")");Intent intent = new Intent(view.getContext(), OrderDetailActivity.class);intent.putExtra(OrderDetailActivity.ARG_ORDER_ID, viewHolder.getOrderId());view.getContext().startActivity(intent);}});break;}}
    Log.d(TAG, "<<onCreateViewHolder(parent=" + parent + ", viewType=" + viewType + ")= " + result);return result;}
    @Overridepublic void onBindViewHolder(ViewHolder viewHolder, Cursor cursor) {Log.d(TAG, "><onBindViewHolder(viewHolder=" + viewHolder + ", cursor=" + cursor + ")");final OrderData orderData = new OrderData(cursor);viewHolder.initFromData(orderData);}}

感谢@marmor,我更新了我的答案。

我认为在视频持有人类构造函数中处理onClick()并通过点击监听器接口将其传递给父类是一个很好的解决方案。

MyAdapter.java

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
private LayoutInflater layoutInflater;private List<MyObject> items;private AdapterView.OnItemClickListener onItemClickListener;
public MyAdapter(Context context, AdapterView.OnItemClickListener onItemClickListener, List<MyObject> items) {layoutInflater = LayoutInflater.from(context);this.items = items;this.onItemClickListener = onItemClickListener;}
@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = layoutInflater.inflate(R.layout.my_row_layout, parent, false);return new ViewHolder(view);}
@Overridepublic void onBindViewHolder(ViewHolder holder, int position) {MyObject item = items.get(position);}
public MyObject getItem(int position) {return items.get(position);}

class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {private TextView title;private ImageView avatar;
public ViewHolder(View itemView) {super(itemView);title = itemView.findViewById(R.id.title);avatar = itemView.findViewById(R.id.avatar);
title.setOnClickListener(this);avatar.setOnClickListener(this);itemView.setOnClickListener(this);}
@Overridepublic void onClick(View view) {//passing the clicked position to the parent classonItemClickListener.onItemClick(null, view, getAdapterPosition(), view.getId());}}}

在其他类中使用适配器:

MyFragment.java

public class MyFragment extends Fragment implements AdapterView.OnItemClickListener {
private RecyclerView recycleview;private MyAdapter adapter;
...
private void init(Context context) {//passing this fragment as OnItemClickListener to the adapteradapter = new MyAdapter(context, this, items);recycleview.setAdapter(adapter);}
@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//you can get the clicked item from the adapter using its positionMyObject item = adapter.getItem(position);
//you can also find out which view was clickedswitch (view.getId()) {case R.id.title://title view was clickedbreak;case R.id.avatar://avatar view was clickedbreak;default://the whole row was clicked}}
}

我使用此方法从RecyclerView启动一个Intent:

@Overridepublic void onBindViewHolder(ViewHolder viewHolder, int i) {
final MyClass myClass = mList.get(i);viewHolder.txtViewTitle.setText(myclass.name);...viewHolder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v){Intent detailIntent = new Intent(mContext, type.class);detailIntent.putExtra("MyClass", myclass);mContext.startActivity(detailIntent);}});

据我理解MLProgrammer-CiM答案,简单地说,可以这样做:

class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{private ImageView image;private TextView title;private TextView price;
public MyViewHolder(View itemView) {super(itemView);image = (ImageView)itemView.findViewById(R.id.horizontal_list_image);title = (TextView)itemView.findViewById(R.id.horizontal_list_title);price = (TextView)itemView.findViewById(R.id.horizontal_list_price);image.setOnClickListener(this);title.setOnClickListener(this);price.setOnClickListener(this);}

@Overridepublic void onClick(View v) {Toast.makeText(context, "Item click nr: "+getLayoutPosition(), Toast.LENGTH_SHORT).show();}}

安卓回收视图onItemClickListener,为什么我们不能尝试这个只是像ListView一样工作。

来源:Link

public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;public interface OnItemClickListener {public void onItemClick(View view, int position);}GestureDetector mGestureDetector;public RecyclerItemClickListener(Context context, OnItemClickListener listener) {mListener = listener;mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {@Overridepublic boolean onSingleTapUp(MotionEvent e) {return true;}});}@Overridepublic boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {View childView = view.findChildViewUnder(e.getX(), e.getY());if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {mListener.onItemClick(childView, view.getChildAdapterPosition(childView));}return false;}
@Overridepublic void onTouchEvent(RecyclerView view, MotionEvent motionEvent) {}
@Overridepublic void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}}

并将其设置为RecyClerView:

    recyclerView = (RecyclerView)rootView. findViewById(R.id.recyclerView);RecyclerView.LayoutManager mLayoutManager = new            LinearLayoutManager(getActivity());recyclerView.setLayoutManager(mLayoutManager);recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(getActivity(), new   RecyclerItemClickListener.OnItemClickListener() {@Overridepublic void onItemClick(View view, int position) {// TODO Handle item clickLog.e("@@@@@",""+position);}}));

在阅读了@陈志立的答案后,这是我的代码:

class NormalViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@Bind(R.id.card_item_normal)CardView cardView;
public NormalViewHolder(View itemView) {super(itemView);ButterKnife.bind(this, itemView);cardView.setOnClickListener(this);}
@Overridepublic void onClick(View v) {if(v instanceof CardView) {// use getAdapterPosition() instead of getLayoutPosition()int itemPosition = getAdapterPosition();removeItem(itemPosition);}}}

而不是实现接口View. OnClickListener内部视图持有人或创建和接口和实现接口在您的活动…我在OnClickListener实现上使用了这段代码。

public static class SimpleStringRecyclerViewAdapterextends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {
// Your initializations goes here...private List<String> mValues;
public static class ViewHolder extends RecyclerView.ViewHolder {
//create a variable mViewpublic final View mView;
/*All your row widgets goes herepublic final ImageView mImageView;public final TextView mTextView;*/
public ViewHolder(View view) {super(view);//Initialize it heremView = view;
/* your row widgets initializations goes heremImageView = (ImageView) view.findViewById(R.id.avatar);mTextView = (TextView) view.findViewById(android.R.id.text1);*/}}
public String getValueAt(int position) {return mValues.get(position);}
public SimpleStringRecyclerViewAdapter(Context context, List<String> items) {
mBackground = mTypedValue.resourceId;mValues = items;}
@Overridepublic ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);view.setBackgroundResource(mBackground);return new ViewHolder(view);}
@Overridepublic void onBindViewHolder(final ViewHolder holder, int position) {holder.mBoundString = mValues.get(position);holder.mTextView.setText(mValues.get(position));
//Here it is simply write onItemClick listener hereholder.mView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Context context = v.getContext();Intent intent = new Intent(context, ExampleActivity.class);
context.startActivity(intent);}});}
@Overridepublic int getItemCount() {return mValues.size();}}

看看我的方法:

首先声明一个这样的接口:

/*** Interface used for delegating item click events in a {@link android.support.v7.widget.RecyclerView}* Created by Alex on 11/28/2015.*/public interface OnRecyclerItemClickListener<T> {
/*** Called when a click occurred inside a recyclerView item view* @param view that was clicked* @param position of the clicked view* @param item the concrete data that is displayed through the clicked view*/void onItemClick(View view, int position, T item);}

然后创建适配器:

public class CustomRecyclerAdapter extends RecyclerView.Adapter {
private class InternalClickListener implements View.OnClickListener{
@Overridepublic void onClick(View v) {if(mRecyclerView != null && mItemClickListener != null){// find the position of the item that was clickedint position = mRecyclerView.getChildAdapterPosition(v);Data data = getItem(position);// notify the main listenermItemClickListener.onItemClick(v, position, data);}}}
private final OnRecyclerItemClickListener mItemClickListener;private RecyclerView mRecyclerView;private InternalClickListener mInternalClickListener;

/**** @param itemClickListener used to trigger an item click event*/public PlayerListRecyclerAdapter(OnRecyclerItemClickListener itemClickListener){mItemClickListener = itemClickListener;mInternalClickListener = new InternalClickListener();}
@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
v.setOnClickListener(mInternalClickListener);
ViewHolder viewHolder = new ViewHolder(v);return viewHolder;}
@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {// do your binding here}
@Overridepublic int getItemCount() {return mDataSet.size();}
@Overridepublic void onAttachedToRecyclerView(RecyclerView recyclerView) {super.onAttachedToRecyclerView(recyclerView);
mRecyclerView = recyclerView;}
@Overridepublic void onDetachedFromRecyclerView(RecyclerView recyclerView) {super.onDetachedFromRecyclerView(recyclerView);
mRecyclerView = null;}
public Data getItem(int position){return mDataset.get(position);}}

现在让我们看看如何从片段中集成它:

public class TestFragment extends Fragment implements OnRecyclerItemClickListener<Data>{private RecyclerView mRecyclerView;
@Overridepublic void onItemClick(View view, int position, Data item) {// do something}
@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {return inflater.inflate(R.layout.test_fragment, container, false);}
@Overridepublic void onViewCreated(View view, Bundle savedInstanceState) {mRecyclerView = view.findViewById(idOfTheRecycler);mRecyclerView .setAdapter(new CustomRecyclerAdapter(this));}

如果你想将onClick()添加到项目的子视图中,例如,项目中的按钮,我发现你可以在你自己的RecyclerView. Adapter的onCreateViewHolder()中轻松完成,就像这样:

        @Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell, null);
Button btn = (Button) v.findViewById(R.id.btn);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//do it}});
return new MyViewHolder(v);}

我不知道这是不是一个好方法,但它很有效。如果有人有更好的想法,很高兴告诉我并纠正我的答案!:)

这对我有效:

@Overridepublic void onBindViewHolder(PlacesListViewAdapter.ViewHolder holder, int position) {------------// Set setOnClickListener(holder);}

@Overridepublic class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
------------
@Overridepublic void onClick(View view) {// Use to get the item clicked getAdapterPosition()}}

我已经这样做了,很简单:

只需为点击回收员查看位置添加1行

int position = getLayoutPosition()

视频持有人类的完整代码:

private class ChildViewHolder extends RecyclerView.ViewHolder {public ImageView imageView;public TextView txtView;
public ChildViewHolder(View itemView) {super(itemView);imageView= (ImageView)itemView.findViewById(R.id.imageView);txtView= (TextView) itemView.findViewById(R.id.txtView);itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Log.i("RecyclerView Item Click Position", String.valueOf(getLayoutPosition()));}});}}

希望这对你有帮助。

如果您有POJO列表并希望从适配器外部单击检索一个,那么这里有一种很容易实现它的方法。

在您的适配器中,为单击事件创建一个侦听器和一个设置它的方法:

public class MyAdapter extends RecyclerView.Adapter<SitesListAdapter.ViewHolder> {...private List<MyPojo> mMyPojos;private static OnItemClickListener mOnItemClickListener;
...public interface OnItemClickListener {public void onItemClick(MyPojo pojo);}
...public void setOnItemClickListener(OnItemClickListener onItemClickListener){mOnItemClickListener = onItemClickListener;}...

}

在你的ViewHolder中,实现onClickListener并创建一个类成员来临时存储视图正在呈现的POJO,这样(这是一个示例,创建一个setter会更好):

public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {public MyPojo mCurrentPojo;...public ViewHolder(View view) {super(v);...view.setOnClickListener(this); //You could set this on part of the layout too}
...@Overridepublic void onClick(View view) {if(mOnItemClickListener != null && mCurrentPojo != null){mOnItemClickListener.onItemClick(mCurrentPojo);}}

回到适配器中,在ViewHolder绑定时设置当前POJO(如果当前视图没有,则设置为null):

@Overridepublic void onBindViewHolder(final ViewHolder holder, final int position) {final MyPojo currentPojo = mMyPojos.get(position);holder.mCurrentPojo = currentPojo;...

就是这样,现在你可以从你的片段/活动中这样使用它:

    mMyAdapter.setOnItemClickListener(new mMyAdapter.OnItemClickListener() {@Overridepublic void onItemClick(MyPojo pojo) {//Do whatever you want with your pojo here}});

伙计们在你的主要活动中使用此代码。非常有效的方法

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.users_list);UsersAdapter adapter = new UsersAdapter(users, this);recyclerView.setAdapter(adapter);adapter.setOnCardClickListner(this);

这是您的Adapter类。

public class UsersAdapter extends RecyclerView.Adapter<UsersAdapter.UserViewHolder> {private ArrayList<User> mDataSet;OnCardClickListner onCardClickListner;

public UsersAdapter(ArrayList<User> mDataSet) {this.mDataSet = mDataSet;}
@Overridepublic UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.user_row_layout, parent, false);UserViewHolder userViewHolder = new UserViewHolder(v);return userViewHolder;}
@Overridepublic void onBindViewHolder(UserViewHolder holder, final int position) {holder.name_entry.setText(mDataSet.get(position).getUser_name());holder.cardView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {onCardClickListner.OnCardClicked(v, position);}});}
@Overridepublic int getItemCount() {return mDataSet.size();}
@Overridepublic void onAttachedToRecyclerView(RecyclerView recyclerView) {super.onAttachedToRecyclerView(recyclerView);}

public static class UserViewHolder extends RecyclerView.ViewHolder {CardView cardView;TextView name_entry;
public UserViewHolder(View itemView) {super(itemView);cardView = (CardView) itemView.findViewById(R.id.user_layout);name_entry = (TextView) itemView.findViewById(R.id.name_entry);}}
public interface OnCardClickListner {void OnCardClicked(View view, int position);}
public void setOnCardClickListner(OnCardClickListner onCardClickListner) {this.onCardClickListner = onCardClickListner;}}

在此之后,您将在活动中获得此覆盖方法。

@Overridepublic void OnCardClicked(View view, int position) {Log.d("OnClick", "Card Position" + position);}

为什么RecyclerView没有onItemClickListener

RecyclerView是一个工具箱,与旧的ListView相比,它具有更少的内置功能和更多的灵活性。onItemClickListener不是从ListView中删除的唯一功能。但它有很多侦听器和方法来扩展它以满足您的喜好,它在合适的人手中更强大;)。

在我看来,RecyclerView中删除的最复杂的功能是快速滚动。大多数其他功能都可以轻松重新实现。

如果你想知道RecyclerView添加了哪些其他很酷的功能,请阅读这个回答另一个问题。

内存效率-onItemClickListener的直接解决方案

RecyclerView发布之后,这个解决方案就是 by雨果·维瑟,一个Android GDE。他为您提供了一个免许可证的类,只需放入您的代码并使用它。

它通过使用RecyclerView.OnChildAttachStateChangeListener展示了RecyclerView引入的一些多功能性。

编辑2019:我的kotlin版本,来自Hugo Visser的java一个,保留在下面

静态编程语言/Java

创建一个文件values/ids.xml并将其放入其中:

<?xml version="1.0" encoding="utf-8"?><resources><item name="item_click_support" type="id" /></resources>

然后将下面的代码添加到您的源代码

静态编程语言

用法:

recyclerView.onItemClick { recyclerView, position, v ->// do it}

(它还支持长项目单击,请参阅下面我添加的另一个功能)。

实现(我对Hugo VisserJava代码的改编):

typealias OnRecyclerViewItemClickListener = (recyclerView: RecyclerView, position: Int, v: View) -> Unittypealias OnRecyclerViewItemLongClickListener = (recyclerView: RecyclerView, position: Int, v: View) -> Boolean
class ItemClickSupport private constructor(private val recyclerView: RecyclerView) {
private var onItemClickListener: OnRecyclerViewItemClickListener? = nullprivate var onItemLongClickListener: OnRecyclerViewItemLongClickListener? = null
private val attachListener: RecyclerView.OnChildAttachStateChangeListener = object : RecyclerView.OnChildAttachStateChangeListener {override fun onChildViewAttachedToWindow(view: View) {// every time a new child view is attached add click listeners to itval holder = this@ItemClickSupport.recyclerView.getChildViewHolder(view).takeIf { it is ItemClickSupportViewHolder } as? ItemClickSupportViewHolder
if (onItemClickListener != null && holder?.isClickable != false) {view.setOnClickListener(onClickListener)}if (onItemLongClickListener != null && holder?.isLongClickable != false) {view.setOnLongClickListener(onLongClickListener)}}
override fun onChildViewDetachedFromWindow(view: View) {
}}
init {// the ID must be declared in XML, used to avoid// replacing the ItemClickSupport without removing// the old one from the RecyclerViewthis.recyclerView.setTag(R.id.item_click_support, this)this.recyclerView.addOnChildAttachStateChangeListener(attachListener)}
companion object {fun addTo(view: RecyclerView): ItemClickSupport {// if there's already an ItemClickSupport attached// to this RecyclerView do not replace it, use itvar support: ItemClickSupport? = view.getTag(R.id.item_click_support) as? ItemClickSupportif (support == null) {support = ItemClickSupport(view)}return support}
fun removeFrom(view: RecyclerView): ItemClickSupport? {val support = view.getTag(R.id.item_click_support) as? ItemClickSupportsupport?.detach(view)return support}}
private val onClickListener = View.OnClickListener { v ->val listener = onItemClickListener ?: return@OnClickListener// ask the RecyclerView for the viewHolder of this view.// then use it to get the position for the adapterval holder = this.recyclerView.getChildViewHolder(v)listener.invoke(this.recyclerView, holder.adapterPosition, v)}
private val onLongClickListener = View.OnLongClickListener { v ->val listener = onItemLongClickListener ?: return@OnLongClickListener falseval holder = this.recyclerView.getChildViewHolder(v)return@OnLongClickListener listener.invoke(this.recyclerView, holder.adapterPosition, v)}
private fun detach(view: RecyclerView) {view.removeOnChildAttachStateChangeListener(attachListener)view.setTag(R.id.item_click_support, null)}
fun onItemClick(listener: OnRecyclerViewItemClickListener?): ItemClickSupport {onItemClickListener = listenerreturn this}
fun onItemLongClick(listener: OnRecyclerViewItemLongClickListener?): ItemClickSupport {onItemLongClickListener = listenerreturn this}
}
/** Give click-ability and long-click-ability control to the ViewHolder */interface ItemClickSupportViewHolder {val isClickable: Boolean get() = trueval isLongClickable: Boolean get() = true}
// Extension functionfun RecyclerView.addItemClickSupport(configuration: ItemClickSupport.() -> Unit = {}) = ItemClickSupport.addTo(this).apply(configuration)
fun RecyclerView.removeItemClickSupport() = ItemClickSupport.removeFrom(this)
fun RecyclerView.onItemClick(onClick: OnRecyclerViewItemClickListener) {addItemClickSupport { onItemClick(onClick) }}fun RecyclerView.onItemLongClick(onLongClick: OnRecyclerViewItemLongClickListener) {addItemClickSupport { onItemLongClick(onLongClick) }}

(请记住您还需要添加一个XML文件,请参阅上面的本节)

静态编程语言版本的附加功能

有时您不希望RecyclerView中的所有项目都可点击。

为了解决这个问题,我引入了ItemClickSupportViewHolder接口,您可以在ViewHolder上使用它来控制哪个项目是可点击的。

示例:

class MyViewHolder(view): RecyclerView.ViewHolder(view), ItemClickSupportViewHolder {override val isClickable: Boolean get() = falseoverride val isLongClickable: Boolean get() = false}

Java

用法:

ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {@Overridepublic void onItemClicked(RecyclerView recyclerView, int position, View v) {// do it}});

(它也支持长项目点击)

实现(我添加的评论):

public class ItemClickSupport {private final RecyclerView mRecyclerView;private OnItemClickListener mOnItemClickListener;private OnItemLongClickListener mOnItemLongClickListener;private View.OnClickListener mOnClickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {if (mOnItemClickListener != null) {// ask the RecyclerView for the viewHolder of this view.// then use it to get the position for the adapterRecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);}}};private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {@Overridepublic boolean onLongClick(View v) {if (mOnItemLongClickListener != null) {RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);}return false;}};private RecyclerView.OnChildAttachStateChangeListener mAttachListener= new RecyclerView.OnChildAttachStateChangeListener() {@Overridepublic void onChildViewAttachedToWindow(View view) {// every time a new child view is attached add click listeners to itif (mOnItemClickListener != null) {view.setOnClickListener(mOnClickListener);}if (mOnItemLongClickListener != null) {view.setOnLongClickListener(mOnLongClickListener);}}
@Overridepublic void onChildViewDetachedFromWindow(View view) {
}};
private ItemClickSupport(RecyclerView recyclerView) {mRecyclerView = recyclerView;// the ID must be declared in XML, used to avoid// replacing the ItemClickSupport without removing// the old one from the RecyclerViewmRecyclerView.setTag(R.id.item_click_support, this);mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);}
public static ItemClickSupport addTo(RecyclerView view) {// if there's already an ItemClickSupport attached// to this RecyclerView do not replace it, use itItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);if (support == null) {support = new ItemClickSupport(view);}return support;}
public static ItemClickSupport removeFrom(RecyclerView view) {ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);if (support != null) {support.detach(view);}return support;}
public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {mOnItemClickListener = listener;return this;}
public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {mOnItemLongClickListener = listener;return this;}
private void detach(RecyclerView view) {view.removeOnChildAttachStateChangeListener(mAttachListener);view.setTag(R.id.item_click_support, null);}
public interface OnItemClickListener {
void onItemClicked(RecyclerView recyclerView, int position, View v);}
public interface OnItemLongClickListener {
boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);}}

它是如何工作的(为什么它是有效的)

此类通过将RecyclerView.OnChildAttachStateChangeListener附加到RecyclerView来工作。每次附加或从RecyclerView中分离子级时都会通知此侦听器。代码使用此将轻击/长按侦听器附加到视图。该侦听器向RecyclerView询问包含位置的RecyclerView.ViewHolder

这比其他解决方案更有效,因为它避免为每个视图创建多个侦听器,并在滚动RecyclerView时继续销毁和创建它们。

如果您需要更多,您还可以调整代码以返回持有者本身。

最后一句话

请记住,通过在列表的每个视图上设置单击侦听器来处理它是完全可以的,就像其他建议的答案一样。

这不是最有效的做法(每次重用视图时都会创建一个新的侦听器),但它有效,在大多数情况下这不是问题。

它也有点反对关注点分离,因为它并不是真正的适配器的任务来委托单击事件。

是的,你可以

public ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
//inflate the view
View view = LayoutInflator.from(parent.getContext()).inflate(R.layout.layoutID,null);
ViewHolder holder = new ViewHolder(view);
//here we can set onClicklistenerview.setOnClickListener(new  View.OnClickListeener(){public void onClick(View v){//action}});
return holder;

在这里你可以处理多个onClick见下面的代码,它是非常有效的

    public class RVNewsAdapter extends RecyclerView.Adapter<RVNewsAdapter.FeedHolder> {
private Context context;List<News> newsList;// Allows to remember the last item shown on screenprivate int lastPosition = -1;
public RVNewsAdapter(List<News> newsList, Context context) {this.newsList = newsList;this.context = context;}
public static class FeedHolder extends RecyclerView.ViewHolder implements OnClickListener {
ImageView img_main;TextView tv_title;Button bt_facebook, bt_twitter, bt_share, bt_comment;

public FeedHolder(View itemView) {super(itemView);
img_main = (ImageView) itemView.findViewById(R.id.img_main);tv_title = (TextView) itemView.findViewById(R.id.tv_title);bt_facebook = (Button) itemView.findViewById(R.id.bt_facebook);bt_twitter = (Button) itemView.findViewById(R.id.bt_twitter);bt_share = (Button) itemView.findViewById(R.id.bt_share);bt_comment = (Button) itemView.findViewById(R.id.bt_comment);
img_main.setOnClickListener(this);bt_facebook.setOnClickListener(this);bt_twitter.setOnClickListener(this);bt_comment.setOnClickListener(this);bt_share.setOnClickListener(this);
}

@Overridepublic void onClick(View v) {
if (v.getId() == bt_comment.getId()) {
Toast.makeText(v.getContext(), "Comment  " , Toast.LENGTH_SHORT).show();
} else if (v.getId() == bt_facebook.getId()) {
Toast.makeText(v.getContext(), "Facebook  " , Toast.LENGTH_SHORT).show();
} else if (v.getId() == bt_twitter.getId()) {
Toast.makeText(v.getContext(), "Twitter  " , Toast.LENGTH_SHORT).show();
} else if (v.getId() == bt_share.getId()) {
Toast.makeText(v.getContext(), "share  " , Toast.LENGTH_SHORT).show();
}else {Toast.makeText(v.getContext(), "ROW PRESSED = " + String.valueOf(getAdapterPosition()), Toast.LENGTH_SHORT).show();}}}
@Overridepublic void onAttachedToRecyclerView(RecyclerView recyclerView) {super.onAttachedToRecyclerView(recyclerView);}
@Overridepublic FeedHolder onCreateViewHolder(ViewGroup parent, int viewType) {View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_row, parent, false);FeedHolder feedHolder = new FeedHolder(view);
return feedHolder;}
@Overridepublic void onBindViewHolder(FeedHolder holder, int position) {
holder.tv_title.setText(newsList.get(position).getTitle());

// Here you apply the animation when the view is boundsetAnimation(holder.img_main, position);}
@Overridepublic int getItemCount() {return newsList.size();}

/*** Here is the key method to apply the animation*/private void setAnimation(View viewToAnimate, int position) {// If the bound view wasn't previously displayed on screen, it's animatedif (position > lastPosition) {Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);viewToAnimate.startAnimation(animation);lastPosition = position;}}

}

使用占位符

@Layout(R.layout.item_view_1)public class View1{
@View(R.id.txt)public TextView txt;
@Resolvepublic void onResolved() {txt.setText(String.valueOf(System.currentTimeMillis() / 1000));}
@Click(R.id.btn)public void onClick(){txt.setText(String.valueOf(System.currentTimeMillis() / 1000));}}

修改了我的评论…

public class MyViewHolder extends RecyclerView.ViewHolder {
private Context mContext;
public MyViewHolder(View itemView) {super(itemView);
mContext = itemView.getContext();
itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {
int itemPosition = getLayoutPosition();Toast.makeText(mContext, "" + itemPosition, Toast.LENGTH_SHORT).show();
}});}

我写了一个库来处理android回收器查看项目单击事件。你可以在https://github.com/ChathuraHettiarachchi/RecycleClick中找到整个教程

RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemClickListener(new RecycleClick.OnItemClickListener() {@Overridepublic void onItemClicked(RecyclerView recyclerView, int position, View v) {// YOUR CODE}});

或处理项目长按您可以使用

RecycleClick.addTo(YOUR_RECYCLEVIEW).setOnItemLongClickListener(new RecycleClick.OnItemLongClickListener() {@Overridepublic boolean onItemLongClicked(RecyclerView recyclerView, int position, View v) {// YOUR CODEreturn true;}});

检查这个我已经用正确的方式实现了所有的事情

回收员ViewHolder类

public class RecyclerViewHolder extends RecyclerView.ViewHolder  {
//view holder is for girdview as we used in the listViewpublic ImageView imageView,imageView2;public RecyclerViewHolder(View itemView) {super(itemView);this.imageView=(ImageView)itemView.findViewById(R.id.image);}
}

适配器

public class RecyclerView_Adapter extends RecyclerView.Adapter<RecyclerViewHolder> {
//RecyclerView will extend to recayclerview Adapterprivate ArrayList<ModelClass> arrayList;private Context context;private static RecyclerViewClickListener itemListener;//constructor of the RecyclerView AdapterRecyclerView_Adapter(Context context,ArrayList<ModelClass> arrayList,RecyclerViewClickListener itemListener){this.context=context;this.arrayList=arrayList;this.itemListener=itemListener;}
@Overridepublic RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {//this method will inflate the custom layout and return as viewHolderLayoutInflater layoutInflater=LayoutInflater.from(parent.getContext());ViewGroup mainGroup=(ViewGroup) layoutInflater.inflate(R.layout.single_item,parent,false);RecyclerViewHolder listHolder=new RecyclerViewHolder(mainGroup);
return listHolder;}
@Overridepublic void onBindViewHolder(RecyclerViewHolder holder, final int position) {
final ModelClass modelClass=arrayList.get(position);//holderRecyclerViewHolder mainHolder=(RecyclerViewHolder)holder;//convert the drawable image into bitmapBitmap image= BitmapFactory.decodeResource(context.getResources(),modelClass.getImage());//set the image into imageViewmainHolder.imageView.setImageBitmap(image);//to handle on click event when clicked on the recyclerview item and// get it through the RecyclerViewHolder class we have defined the views theremainHolder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//get the position of the image which is clickeditemListener.recyclerViewListClicked(v,position);}});
}
@Overridepublic int getItemCount() {return (null!=arrayList?arrayList.size():0);}}

的接口

public interface RecyclerViewClickListener {
//this is method to handle the event when clicked on the image in Recyclerviewpublic void recyclerViewListClicked(View v,int position);}
//and to call this method in activityRecyclerView_Adapter adapter=new RecyclerView_Adapter(Wallpaper.this,arrayList,this);recyclerView.setAdapter(adapter);adapter.notifyDataSetChanged();

@Overridepublic void  recyclerViewListClicked(View v,int position){
imageView.setImageResource(wallpaperImages[position]);
}

后续MLProgrammer-CiM优秀的RxJava解决方案

消费/观察点击次数

Consumer<String> mClickConsumer = new Consumer<String>() {@Overridepublic void accept(@NonNull String element) throws Exception {Toast.makeText(getApplicationContext(), element +" was clicked", Toast.LENGTH_LONG).show();}};
ReactiveAdapter rxAdapter = new ReactiveAdapter();rxAdapter.getPositionClicks().subscribe(mClickConsumer);

RxJava 2.+

将原始tl; dr修改为:

public Observable<String> getPositionClicks(){return onClickSubject;}

PublishSubject#asObservable()已删除。只需返回PublishSubject,即Observable

为您RecyclerView访问rowLayout(cell)中的mainView,并在您的OnBindViewHolder中编写此代码:

    @Overridepublic void onBindViewHolder(MyViewHolder holder, final int position) {Movie movie = moviesList.get(position);holder.mainView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {System.out.println("pos " + position);}});}

最简单的方法如下:

在Adapter类开始时声明全局变量:

// Store out here so we can resuseprivate View yourItemView;

然后在onBindViewHolder动态链接方法中设置OnClickListener:

@Overridepublic void onBindViewHolder(BusinessAdapter.ViewHolder holder, int position) {
// Set up the on click listeneryourItemView.setOnClickListener(new View.OnClickListener() {
@Overridepublic void onClick(View v) {Toast.makeText(mContext,Integer.toString(position),Toast.LENGTH_SHORT).show();}});
}

所有其他答案都是错误的。

它为我工作。希望它会帮助。最简单的方法。

内部视图支架

class GeneralViewHolder extends RecyclerView.ViewHolder {View cachedView = null;
public GeneralViewHolder(View itemView) {super(itemView);cachedView = itemView;}

内部OnBindViewHolder()

@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {final GeneralViewHolder generalViewHolder = (GeneralViewHolder) holder;generalViewHolder.cachedView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(context, "item Clicked at "+position, Toast.LENGTH_SHORT).show();}});

让我知道,你对这个解决方案有什么疑问吗?

 main_recyclerview.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {@Overridepublic boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e){int position=rv.getChildAdapterPosition(rv.findChildViewUnder(e.getX(),e.getY()));
switch (position){case 0:{wifi(position);adapter2.notifyDataSetChanged();}break;
case 1:{sound(position);adapter2.notifyDataSetChanged();}break;
case 2:{bluetooth(position);adapter2.notifyDataSetChanged();}break;

}return true;}
@Overridepublic void onTouchEvent(RecyclerView rv, MotionEvent e){
}
@Overridepublic void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}});

回收站动画未测试,其他正常。我觉得已经优化到最大。界面有其他用途,您可以暂时忽略。

public abstract class BaseAdapterRV<VH extends BaseViewHolder> extends RecyclerView.Adapter<VH> implements AdapterInterface {public final String TAG = getClass().getSimpleName();
protected final Activity mActivity;protected final LayoutInflater mInflater;protected ItemClickInterface<?, Integer> mListener;
public BaseAdapterRV(Activity activity) {mActivity = activity;mInflater = LayoutInflater.from(mActivity);}
@Overridepublic final VH onCreateViewHolder(ViewGroup parent, int viewType) {return onCreateViewHolder(parent, viewType, mInflater);}
@Overridepublic final void onBindViewHolder(VH holder, int position) {holder.itemView.setTag(R.id.tag_view_click, position);//创建点击事件holder.itemView.setOnClickListener(mListener);holder.itemView.setOnLongClickListener(mListener);onBindVH(holder, position);}

///////////////////////////////////////////////////////////////////////////// 以下是增加的方法///////////////////////////////////////////////////////////////////////////
/*** 注意!涉及到notifyItemInserted刷新时立即获取position可能会不正确* 里面也有onItemLongClick*/public void setOnItemClickListener(ItemClickInterface<?, Integer> listener) {mListener = listener;notifyDataSetChanged();}
@NonNullprotected abstract VH onCreateViewHolder(ViewGroup parent, int viewType, LayoutInflater inflater);
protected abstract void onBindVH(VH holder, int position);
}

这是界面

/*** OnItemClickListener的接口* 见子类实现{@link OnItemClickListener}{@link OnItemItemClickListener}*/public interface ItemClickInterface<DATA1, DATA2> extends View.OnClickListener, View.OnLongClickListener {
void onItemClick(DATA1 data1, DATA2 data2);
boolean onItemLongClick(DATA1 data1, DATA2 data2);}

这是一个抽象类

public abstract class OnItemClickListener<DATA> implements ItemClickInterface<View, DATA> {@Overridepublic void onClick(View v) {onItemClick(v, (DATA) v.getTag(R.id.tag_view_click));}
@Overridepublic boolean onLongClick(View v) {return onItemLongClick(v, (DATA) v.getTag(R.id.tag_view_click));}
@Overridepublic boolean onItemLongClick(View view, DATA data) {return false;}}

你只需要它

    mAdapter.setOnItemClickListener(new OnItemClickListener<Integer>() {@Overridepublic void onItemClick(View view, Integer integer) {
}
@Overridepublic boolean onItemLongClick(View view, Integer integer) {return true;}});

RecyClerView没有onItemClickListener,因为RecyClerView负责回收视图(惊喜!),所以它是回收的视图的责任来处理它收到的点击事件。

这实际上使其更易于使用,特别是如果您有可以在多个位置单击的项目。


无论如何,检测点击RecyclerView项目非常容易。你需要做的就是定义一个接口(如果你不使用静态编程语言,在这种情况下你只需传入一个lambda):

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {private final Clicks clicks;
public MyAdapter(Clicks clicks) {this.clicks = clicks;}
private List<MyObject> items = Collections.emptyList();
public void updateData(List<MyObject> items) {this.items = items;notifyDataSetChanged(); // TODO: use ListAdapter for diffing instead if you need animations}
public interface Clicks {void onItemSelected(MyObject myObject, int position);}
public class MyViewHolder extends RecyclerView.ViewHolder {private MyObject myObject;
public MyViewHolder(View view) {super(view);// bind viewsview.setOnClickListener((v) -> {int adapterPosition = getBindingAdapterPosition();if(adapterPosition >= 0) {clicks.onItemSelected(myObject, adapterPosition);}});}
public void bind(MyObject myObject) {this.myObject = myObject;// bind data to views}}}

静态编程语言:

class MyAdapter(val itemClicks: (MyObject, Int) -> Unit): RecyclerView.Adapter<MyViewHolder>() {private var items: List<MyObject> = Collections.emptyList()
fun updateData(items: List<MyObject>) {this.items = itemsnotifyDataSetChanged() // TODO: use ListAdapter for diffing instead if you need animations}
inner class MyViewHolder(val myView: View): RecyclerView.ViewHolder(myView) {private lateinit var myObject: MyObject
init {// binds viewsmyView.onClick {val adapterPosition = getBindingAdapterPosition()if(adapterPosition >= 0) {itemClicks.invoke(myObject, adapterPosition)}}}
fun bind(myObject: MyObject) {this.myObject = myObject// bind data to views}}}

不要需要做的事情:

1.你不需要手动拦截触摸事件

2.)你不需要弄乱孩子附加状态更改侦听器

3.)你不需要从RxJava发布主题/发布中继

只需使用单击侦听器。

我找到了使用androidx生命周期可变活数据的最短方法之一

适配器:

private val onItemClickListener = MutableLiveData<YourAdapterItem>()

override fun onBindViewHolder(holder: GifsViewHolder, position: Int) {holder.itemView.setOnClickListener { onItemClickListener.value = gifs[position] }}fun getOnItemClickListener(): MutableLiveData<Gif> {return onItemClickListener}

任何地方MainActive

    yourFancyAdapter.getOnItemClickListener().observe(this, Observer {println(it)})