为什么 RecyclerView 没有 onItemClickListener()? [英] Why doesn't RecyclerView have onItemClickListener()?

查看:20
本文介绍了为什么 RecyclerView 没有 onItemClickListener()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was exploring RecyclerView and I was surprised to see that RecyclerView does not have onItemClickListener().

我有两个问题.

我想知道为什么 Google 删除了 onItemClickListener()?

I want to know why Google removed onItemClickListener()?

是否存在性能问题或其他问题?

Is there a performance issue or something else?

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

I solved my problem by writing onClick in my RecyclerView.Adapter:

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);
    }

    @Override
    public void onClick(View v) {

    }
}

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

Is this ok / is there any better way?

推荐答案

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

tl;dr 2016 Use RxJava and a PublishSubject to expose an Observable for the clicks.

public class ReactiveAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    String[] mDataset = { "Data", "In", "Adapter" };

    private final PublishSubject<String> onClickSubject = PublishSubject.create();

    @Override 
    public void onBindViewHolder(final ViewHolder holder, int position) {
        final String element = mDataset[position];

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               onClickSubject.onNext(element);
            }
        });
    }

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

原帖:

自从引入ListViewonItemClickListener 就出现了问题.当您拥有任何内部元素的点击侦听器时,回调将不会被触发,但不会被通知或有详细记录(如果有的话),因此存在很多混淆和问题.

Since the introduction of ListView, onItemClickListener has been problematic. The moment you have a click listener for any of the internal elements the callback would not be triggered but it wasn't notified or well documented (if at all) so there was a lot of confusion and SO questions about it.

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

Given that RecyclerView takes it a step further and doesn't have a concept of a row/column, but rather an arbitrarily laid out amount of children, they have delegated the onClick to each one of them, or to programmer implementation.

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

Think of Recyclerview not as a ListView 1:1 replacement but rather as a more flexible component for complex use cases. And as you say, your solution is what google expected of you. Now you have an adapter who can delegate onClick to an interface passed on the constructor, which is the correct pattern for both ListView and Recyclerview.

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);
    }

    @Override
    public 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" };

   @Override
   public 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) 
    @Override 
    public 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 used
        holder.txtViewTitle.setText(mDataset[position]);
    } 

    // Return the size of your dataset (invoked by the layout manager) 
    @Override 
    public int getItemCount() { 
        return mDataset.length;
    } 
  ...

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

Now look into that last piece of code: onCreateViewHolder(ViewGroup parent, int viewType) the signature already suggest different view types. For each one of them you'll require a different viewholder too, and subsequently each one of them can have a different set of clicks. Or you can just create a generic viewholder that takes any view and one onClickListener and applies accordingly. Or delegate up one level to the orchestrator so several fragments/activities have the same list with different click behaviour. Again, all flexibility is on your side.

这是一个真正需要的组件,与我们迄今为止对 ListView 的内部实现和改进非常接近.好在 Google 终于承认了这一点.

It is a really needed component and fairly close to what our internal implementations and improvements to ListView were until now. It's good that Google finally acknowledges it.

这篇关于为什么 RecyclerView 没有 onItemClickListener()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆