Comment obtenir un contexte dans un adaptateur de vue recycleur

129

J'essaie d'utiliser la bibliothèque Picasso pour pouvoir charger l'URL dans imageView, mais je ne suis pas en mesure d'obtenir le contextpour utiliser correctement la bibliothèque Picasso.

public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.ViewHolder> {
    private List<Post> mDataset;



    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView txtHeader;
        public ImageView pub_image;
        public ViewHolder(View v) {
            super(v);
            txtHeader = (TextView) v.findViewById(R.id.firstline);
            pub_image = (ImageView) v.findViewById(R.id.imageView);


        }
    }




    // Provide a suitable constructor (depends on the kind of dataset)
    public FeedAdapter(List<Post> myDataset) {
        mDataset = myDataset;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public FeedAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.feedholder, parent, false);
        // set the view's size, margins, paddings and layout parameters
        ViewHolder vh = new ViewHolder(v);
        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

        holder.txtHeader.setText(mDataset.get(position).getPost_text());

        Picasso.with(this.context).load("http://i.imgur.com/DvpvklR.png").into(holder.pub_image);


    }

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

}
Étranger B.
la source

Réponses:

290

Vous avez ici quelques options:

  1. Passez Contexten argument à FeedAdapter et conservez-le comme champ de classe
  2. Utilisez l'injection de dépendances pour injecter Contextlorsque vous en avez besoin. Je suggère fortement de lire à ce sujet. Il existe un excellent outil pour cela - Dagger by Square
  3. Obtenez-le de n'importe quel Viewobjet. Dans votre cas, cela pourrait fonctionner pour vous:

    holder.pub_image.getContext()

    Comme pub_imagec'est un ImageView.

pelotasplus
la source
64
Je préfère la troisième option, obtenir le contexte de la vue. C'est la solution la plus simple et la plus directe.
Dick Lucas
ou, mieux encore, transmettez l'instance Picasso, plutôt que de maintenir une instance Picasso sur l'instance de classe et de la charger paresseusement.
Eric Cochran
8
Chaque ViewHolder contient une instance de itemView que vous transmettez au constructeur. Utilisez celui-ci comme ceci: itemView.getContext ()
Andrei Lupsa
1
Vous ne pouvez pas faire le n ° 2, n'est-ce pas? J'ai essayé cela, mais cela finira par être le vôtre ApplicationContextet non lié à l'activité, ce qui entraînera un crash d'exécution à partir de Glide.
boltup_im_coding
comment passer l'objet composant à l'adaptateur au cas où je voudrais utiliser # 2?
Ezio
32

Vous pouvez ajouter une variable globale:

private Context context;

puis attribuez le contexte à partir d'ici:

@Override
public FeedAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
    // create a new view
    View v=LayoutInflater.from(parent.getContext()).inflate(R.layout.feedholder, parent, false);
    // set the view's size, margins, paddings and layout parameters
    ViewHolder vh = new ViewHolder(v);
    // set the Context here 
    context = parent.getContext();
    return vh;
}

Bon codding :)

Farhad Navayazdan
la source
A travaillé pour moi aussi! Merci
Kenny Dabiri
21
Je suggère fortement CONTRE d'avoir des références globales au contexte. Cela pourrait entraîner d'horribles problèmes de fuite de mémoire !!
solidak
1
si vous sous-classez le visualiseur, il peut être privé.
r3dm4n
Si l'adaptateur est attaché à un RecyclerView, il est garanti que ce contexte est de toute façon nécessaire. Si vous pouvez détacher l'adaptateur, alors tout va bien sauf si, pour une raison quelconque, vous détenez une référence forte à cet adaptateur après qu'il a été détaché, auquel cas vous devez effacer le contexte mis en cache, il existe une méthode comme onDetachedFromRecyclerViewou quelque chose.
androidguy
19

Réponse courte:

Context context;

@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
    super.onAttachedToRecyclerView(recyclerView);
    context = recyclerView.getContext();
}

Explication pourquoi les autres réponses ne sont pas géniales:

  1. Le passage Contextà l'adaptateur est totalement inutile, car RecyclerViewvous pouvez y accéder depuis l'intérieur de la classe
  2. Obtenir Contextau ViewHolderniveau signifie que vous le faites chaque fois que vous liez ou créez unViewHolder . Vous dupliquez des opérations.
  3. Je ne pense pas que vous ayez à vous soucier d'une fuite de mémoire. Si votre adaptateur persiste en dehors de votre Activitydurée de vie (ce qui serait étrange), vous avez déjà une fuite.
Maciej Beimcik
la source
Dans ce cas, devons-nous implémenter onDetachedFromRecyclerView()et libérer le contexte?
John Pang
@JohnPang pas vraiment à moins que vous ne vouliez être extrêmement défensif. Si vous conservez la référence de l'adaptateur dans l'activité, vous êtes en sécurité.
Maciej Beimcik
17

Vous pouvez utiliser pub_image context ( holder.pub_image.getContext()):

@Override
public void onBindViewHolder(ViewHolder ViewHolder, int position) {

    holder.txtHeader.setText(mDataset.get(position).getPost_text());

    Picasso.with(holder.pub_image.getContext()).load("http://i.imgur.com/DvpvklR.png").into(holder.pub_image);


}
Ahmad Aghazadeh
la source
6

Vous pouvez définir:

Context ctx; 

Et lors de l' onCreateinitialisation ctxsur:

ctx=parent.getContext(); 

Remarque: Parent est un ViewGroup.

Marcos Vitouley
la source
5

Première déclaration mondiale

Context mContext;

passer le contexte au constructeur, en le modifiant.

public FeedAdapter(List<Post> myDataset, Context context) {
    mDataset = myDataset;
    this.mContext = context;
}

puis utilisez le mContextpartout où vous en avez besoin

Blue_Alien
la source
5

Vous pouvez utiliser comme ceci view.getContext ()

Exemple

holder.tv_room_name.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            Toast.makeText(v.getContext(), "", Toast.LENGTH_SHORT).show();


        }
    });
Arpit Patel
la source
5

vous pouvez utiliser ceci:

itemView.getContext()
张张
la source
4

Créez un constructeur de FeedAdapter:

Context context; //global
public FeedAdapter(Context context)
{
   this.context = context;  
}

et en activité

FeedAdapter obj = new FeedAdapter(this);
blockwala
la source
2

Ajoutez d'abord une variable globale

Context mContext;

Puis changez votre constructeur en ceci

public FeedAdapter(Context context, List<Post> myDataset) {
    mContext = context;
    mDataset = myDataset;
}

Passez votre contexte lors de la création de l'adaptateur.

FeedAdapter myAdapter = new FeedAdapter(this,myDataset);
AKT
la source
1
View mView;
mView.getContext();
Rohit Daftari
la source
Bien que ce code puisse résoudre la question, inclure une explication sur comment et pourquoi cela résout le problème aiderait vraiment à améliorer la qualité de votre message et entraînerait probablement plus de votes à la hausse. N'oubliez pas que vous répondez à la question des lecteurs à l'avenir, pas seulement à la personne qui la pose maintenant. Veuillez modifier votre réponse pour ajouter des explications et donner une indication des limites et des hypothèses applicables. De l'avis
double-beep