Come ottenere un contesto in un adattatore vista riciclatore


129

Sto cercando di utilizzare la libreria Picasso per essere in grado di caricare l'URL in imageView, ma non sono in grado contextdi utilizzare correttamente la libreria 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();
    }

}

Risposte:


290

Hai alcune opzioni qui:

  1. Passa Contextcome argomento a FeedAdapter e mantienilo come campo di classe
  2. Usa l'iniezione di dipendenza per iniettare Contextquando ne hai bisogno. Consiglio vivamente di leggerlo. C'è un ottimo strumento per questo - Dagger by Square
  3. Ottienilo da qualsiasi Viewoggetto. Nel tuo caso questo potrebbe funzionare per te:

    holder.pub_image.getContext()

    Come pub_imageè un ImageView.


64
Preferisco la terza opzione, ottenendo il contesto dalla vista. È la soluzione più semplice e diretta.
Dick Lucas,

o, molto meglio, passare nell'istanza di Picasso, anziché tenere un'istanza di Picasso sull'istanza della classe e caricarla in modo lento.
Eric Cochran,

8
Ogni ViewHolder contiene un'istanza di itemView che passi nel costruttore. Usa quello come questo: itemView.getContext ()
Andrei Lupsa,

1
Non puoi fare il secondo, vero? Ci ho provato, ma questo finirà per essere tuo ApplicationContexte non legato all'attività, portando a un crash del runtime dall'interno di Glide.
boltup_im_coding

come passare l'oggetto componente all'adattatore nel caso volessi usare # 2?
Ezio,

32

È possibile aggiungere una variabile globale:

private Context context;

quindi assegnare il contesto da qui:

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

Happy Codding :)


Ha funzionato anche per me! Grazie
Kenny Dabiri il

21
Consiglio vivamente CONTRO di avere riferimenti globali al contesto. Ciò potrebbe causare orribili problemi di perdita di memoria !!
solidak,

1
se esegui la sottoclasse del visualizzatore, può essere privato.
r3dm4n,

Se l'adattatore è collegato a RecyclerView, quel contesto è comunque garantito. Se potresti scollegare l'adattatore, allora va ancora bene a meno che per qualche motivo non mantieni un forte riferimento a questo adattatore dopo che è stato staccato, nel qual caso dovresti cancellare il contesto memorizzato nella cache, c'è un metodo simile onDetachedFromRecyclerViewo qualcosa del genere.
androidguy il

19

Risposta breve:

Context context;

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

Spiegazione del perché le altre risposte non sono grandi:

  1. Il passaggio Contextall'adattatore non è assolutamente necessario, poiché RecyclerViewè possibile accedervi dall'interno della classe
  2. Ottenere Contexta ViewHolderlivello significa che lo fai ogni volta che leghi o crei un ViewHolder. Si duplicano le operazioni.
  3. Non penso che ti debba preoccupare di eventuali perdite di memoria. Se l'adattatore persiste al di fuori della Activitydurata della tua vita (il che sarebbe strano), hai già una perdita.

In questo caso, dobbiamo implementare onDetachedFromRecyclerView()e rilasciare il contesto?
John Pang,

@JohnPang non a meno che tu non voglia essere estremamente difensivo. Se si mantiene il riferimento dell'adattatore all'interno dell'Attività, si è al sicuro.
Maciej Beimcik,

17

Puoi utilizzare 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);


}

6

Puoi definire:

Context ctx; 

E su onCreateinizializzazione ctxa:

ctx=parent.getContext(); 

Nota: Parent è un ViewGroup.


5

Prima dichiarare a livello globale

Context mContext;

passare il contesto con il costruttore, modificandolo.

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

quindi usa mContextovunque tu ne abbia bisogno


5

Puoi usare come questo view.getContext ()

Esempio

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

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


        }
    });


4

Crea un costruttore di FeedAdapter:

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

e in attività

FeedAdapter obj = new FeedAdapter(this);

2

Per prima cosa aggiungi una variabile globale

Context mContext;

Quindi cambia il tuo costruttore in questo

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

Passa il tuo contesto durante la creazione dell'adattatore.

FeedAdapter myAdapter = new FeedAdapter(this,myDataset);

1
View mView;
mView.getContext();

Sebbene questo codice possa risolvere la domanda, inclusa una spiegazione di come e perché questo risolva il problema, contribuirebbe davvero a migliorare la qualità del tuo post e probabilmente a dare più voti positivi. Ricorda che stai rispondendo alla domanda per i lettori in futuro, non solo per la persona che chiede ora. per favore modificare la risposta per aggiungere spiegazioni e dare un'indicazione di ciò si applicano le limitazioni e le assunzioni. Dalla recensione
Doppio segnale acustico
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.