RecyclerView に onItemClickListener() がないのはなぜですか? 質問する

RecyclerView に onItemClickListener() がないのはなぜですか? 質問する

探検していたら、がないRecyclerViewことに驚きました。RecyclerViewonItemClickListener()

質問が2つあります。

主な質問

Google が を削除した理由を知りたいですonItemClickListener()

パフォーマンスの問題か何か他のものがありますか?

二次質問

onClick私は次のように書いて問題を解決しました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) {

    }
}

これで大丈夫ですか?/もっと良い方法はありますか?

ベストアンサー1

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

    @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問題がありました。内部要素のいずれかにクリック リスナーがあると、コールバックはトリガーされませんが、通知も適切に文書化もされていなかったため (まったく文書化されていなかったとしても)、多くの混乱が生じ、SO に関する質問も寄せられました。

さらにRecyclerView一歩進んで、行/列の概念がなく、任意に配置された数の子があることを考えると、onClick はそれぞれの子、またはプログラマーの実装に委任されています。

Recyclerviewを 1:1 の置き換えとしてではなく、複雑なユースケースに対応するより柔軟なコンポーネントとして考えてください。そして、おっしゃるとおり、あなたのソリューションは Google が期待していたものです。これで、コンストラクターに渡されたインターフェースに onClick を委任できるアダプターができました。これは、とListViewの両方にとって正しいパターンです。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);
    }

}

そしてアダプタに

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)シグネチャは既にさまざまなビュー タイプを示しています。それぞれに異なるビューホルダーも必要になり、その結果、それぞれに異なるクリック セットを設定できます。または、任意のビューと 1 つを取得してonClickListenerそれに応じて適用する汎用ビューホルダーを作成することもできます。または、オーケストレーターに 1 レベル上を委任して、複数のフラグメント/アクティビティに異なるクリック動作を持つ同じリストを持たせることもできます。繰り返しますが、柔軟性はすべてあなたの側にあります。

これは本当に必要なコンポーネントであり、ListViewこれまでの社内実装や改善にかなり近いものです。Google がようやくこれを認めてくれたのは良いことです。

おすすめ記事