Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
161 views
in Technique[技术] by (71.8m points)

java - 为什么RecyclerView没有onItemClickListener()? [关闭](Why doesn't RecyclerView have onItemClickListener()? [closed])

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

(我在浏览RecyclerView ,惊讶地发现RecyclerView没有onItemClickListener() 。)

Because RecyclerView extends

(由于RecyclerView扩展)

android.view.ViewGroup

(android.view.ViewGroup)

and ListView extends

(和ListView扩展)

android.widget.AbsListView

(android.widget.AbsListView)

.

(。)

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

(但是我通过在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);
    }

    @Override
    public void onClick(View v) {

    }
}

But still I want to know why Google removed onItemClickListener() ?

(但是我仍然想知道为什么Google删除了onItemClickListener() ?)

Is there a performance issue or something else?

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

  ask by Tarun Varshney translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

(tl 2016年博士使用RxJava和PublishSubject公开点击的可观察对象。)

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

Original Post:

(原始帖子:)

Since the introduction of ListView , onItemClickListener has been problematic.

(自从引入ListView以来, onItemClickListener一直存在问题。)

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.

(当您拥有用于任何内部元素的单击侦听器时,将不会触发该回调,但是该回调没有得到通知或没有得到充分的文档记录(如果有的话)(因此),因此存在很多混乱和疑问。)

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更进一步,它没有行/列的概念,而是任意布局的子代,因此他们将onClick委托给了每个子代或程序员实现。)

Think of Recyclerview not as a ListView 1:1 replacement but rather as a more flexible component for complex use cases.

(不要将Recyclerview视为ListView 1:1的替代品,而Recyclerview视为用于复杂用例的更灵活的组件。)

And as you say, your solution is what google expected of you.

(正如您所说,您的解决方案就是Google对您的期望。)

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 .

(现在,您有了一个适配器,可以将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);
    }

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

}

and then on your adapter

(然后在您的适配器上)

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

Now look into that last piece of code: onCreateViewHolder(ViewGroup parent, int viewType) the signature already suggest different view types.

(现在查看最后一段代码: onCreateViewHolder(ViewGroup parent, int viewType)签名已经建议了不同的视图类型。)

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.

(或者,您可以只创建一个通用的视图持有者,该视图持有者使用任何视图和一个onClickListener并相应地应用。)

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.

(同样,所有灵活性都在您身边。)

It is a really needed component and fairly close to what our internal implementations and improvements to ListView were until now.

(它是一个真正需要的组件,与我们迄今为止对ListView内部实现和改进非常接近。)

It's good that Google finally acknowledges it.

(Google最终承认这一点是一件好事。)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...