1048 votes

Pourquoi n ' t RecyclerView ont onItemClickListener() ?

Je ne sais pas si je me suis poser la bonne question. J'ai été d'explorer RecyclerView et j'ai été surpris de voir que RecyclerView n'a pas onItemClickListener(). Parce que RecyclerView s'étend android.vue.ViewGroup. et ListView s'étend android.widget de.AbsListView. Cependant, j'ai résolu mon problème en écrivant onClick dans mon RecyclerView.Adaptateur:

  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) {
        // TODO Auto-generated method stub

    }
}

Mais encore, je veux savoir pourquoi Google retire onItemClickListener()? Est-il un problème de performance ou autre chose?

1246voto

MLProgrammer-CiM Points 1080

Depuis l'introduction de la ListView, onItemClickListener a été problématique. Le moment où vous avez un écouteur de clics pour l'un quelconque des éléments internes de la fonction de rappel ne serait pas déclenché, mais il n'était pas informé ou bien documenté (si) donc il y avait beaucoup de confusion et DONC des questions à ce sujet.

Étant donné que RecyclerView prend un peu plus loin et ne pas avoir un concept d'une ligne/colonne, mais plutôt arbitrairement fixés montant de leurs enfants, ils ont délégué la onClick pour chacun d'eux, ou de programmeur de mise en œuvre.

Pensez à Recyclerview pas comme une ListView remplacement 1:1, mais plutôt comme un composant plus flexible pour des complexes de cas d'utilisation. Et comme vous le dites, votre solution est-ce que google attend de vous. Maintenant vous avez une carte qui peut déléguer onClick à une interface passé sur le constructeur, qui est le bon modèle pour les deux ListView et 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);
    // Is this needed or handled automatically by RecyclerView.ViewHolder?
    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);
}

}

et puis sur votre carte

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("Poh-tah-tos"); };
           public void onTomato(ImageView callerImage) { Log.d("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;
    } 

  ...

Maintenant, regardez dans ce dernier morceau de code: onCreateViewHolder(ViewGroup parent, int viewType) à la signature d'ores et déjà proposer différents types de vues. Pour chacun d'eux, vous aurez besoin d'un autre viewholder trop, et par la suite, chaque un seul d'entre eux peut avoir un ensemble différent de clics. Ou vous pouvez simplement créer un générique viewholder qui prend n'importe quelle vue et un onClickListener et s'applique en conséquence. Ou délégué d'un niveau à l'orchestrator plusieurs fragments/activités qui ont la même liste avec différents sur le comportement. Encore une fois, toute la souplesse est de votre côté.

C'est vraiment une composante nécessaire et assez proche de ce que nos implémentations internes et des améliorations à la liste ont été jusqu'à maintenant. Il est bon que Google reconnaît.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X