Cómo obtener un contexto en un adaptador de vista de reciclador

129

Estoy tratando de usar la biblioteca picasso para poder cargar la url en imageView, pero no puedo contextusar la biblioteca picasso correctamente.

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

}
Extraño B.
fuente

Respuestas:

290

Tienes algunas opciones aquí:

  1. Pase Contextcomo argumento a FeedAdapter y manténgalo como campo de clase
  2. Use la inyección de dependencia para inyectar Contextcuando lo necesite. Sugiero leer sobre esto. Hay una gran herramienta para eso: Dagger by Square
  3. Obtenlo de cualquier Viewobjeto. En su caso, esto podría funcionar para usted:

    holder.pub_image.getContext()

    Como pub_imagees a ImageView.

pelotasplus
fuente
64
Prefiero la tercera opción, obtener el contexto de la vista. Es la solución más simple y directa.
Dick Lucas
o, mucho mejor, pasar la instancia de Picasso, en lugar de mantener una instancia de Picasso en la instancia de clase y cargarla de forma diferida.
Eric Cochran
8
Cada ViewHolder contiene una instancia de itemView que pasa en el constructor. Use ese como este: itemView.getContext ()
Andrei Lupsa
1
No puedes hacer el # 2, ¿verdad? Lo intenté, pero esto terminará siendo tuyo ApplicationContexty no atado a la actividad, lo que provocará un bloqueo en tiempo de ejecución desde Glide.
boltup_im_coding
¿Cómo pasar el objeto componente al adaptador en caso de que quiera usar el # 2?
Ezio
32

Puede agregar una variable global:

private Context context;

luego asigne el contexto desde aquí:

@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 :)

Farhad Navayazdan
fuente
¡Trabajó para mí también! Gracias
Kenny Dabiri
21
Sugiero encarecidamente CONTRA tener referencias globales al contexto. ¡Esto podría provocar problemas horribles de pérdida de memoria!
solidak
1
si subclasifica el marcador de vista, puede ser privado.
r3dm4n
Si el adaptador está conectado a un RecyclerView, se garantiza que ese contexto será necesario de todos modos. Si puede desconectar el adaptador, entonces todavía está bien, a menos que, por alguna razón, tenga una fuerte referencia a este adaptador después de haberlo desconectado, en cuyo caso debe borrar el contexto almacenado en caché, hay un método similar onDetachedFromRecyclerViewo algo así.
androidguy
19

Respuesta corta:

Context context;

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

Explicación de por qué otras respuestas no son geniales:

  1. Pasar Contextal adaptador es completamente innecesario, ya RecyclerViewque puede acceder a él desde dentro de la clase
  2. Obtener Contexta ViewHoldernivel significa que lo haces cada vez que unes o creas unViewHolder . Duplicas operaciones.
  3. No creo que deba preocuparse por ninguna pérdida de memoria. Si su adaptador permanece fuera de su Activityvida útil (lo que sería extraño), entonces ya tiene una fuga.
Maciej Beimcik
fuente
En este caso, ¿implementaremos onDetachedFromRecyclerView()y publicaremos el contexto?
John Pang
@JohnPang no realmente a menos que quieras estar extremadamente a la defensiva. Si mantiene la referencia del adaptador dentro de la Actividad, está a salvo.
Maciej Beimcik
17

Puede usar 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
fuente
6

Puedes definir:

Context ctx; 

Y en onCreateinicializar ctxa:

ctx=parent.getContext(); 

Nota: Parent es un ViewGroup.

Marcos vitouley
fuente
5

Primero declarar globalmente

Context mContext;

pasar contexto con el constructor, modificándolo.

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

luego use el lugar mContextdonde lo necesite

Blue_Alien
fuente
5

Puede usar así view.getContext ()

Ejemplo

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

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


        }
    });
Arpit Patel
fuente
5

puedes usar esto:

itemView.getContext()
张家 宝
fuente
4

Cree un constructor de FeedAdapter:

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

y en actividad

FeedAdapter obj = new FeedAdapter(this);
blockwala
fuente
2

Primero agregue una variable global

Context mContext;

Luego cambia tu constructor a esto

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

Pasan su contexto al crear el adaptador.

FeedAdapter myAdapter = new FeedAdapter(this,myDataset);
AKT
fuente
1
View mView;
mView.getContext();
Rohit Daftari
fuente
Si bien este código puede resolver la pregunta, incluir una explicación de cómo y por qué esto resuelve el problema realmente ayudaría a mejorar la calidad de su publicación, y probablemente resultaría en más votos positivos. Recuerde que está respondiendo la pregunta para los lectores en el futuro, no solo la persona que pregunta ahora. Por favor, editar su respuesta para agregar explicaciones y dar una indicación de lo que se aplican limitaciones y supuestos. De la opinión
doble pitido