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

}

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.


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


¡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.

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


}

6

Puedes definir:

Context ctx; 

Y en onCreateinicializar ctxa:

ctx=parent.getContext(); 

Nota: Parent es un ViewGroup.


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


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


        }
    });


4

Cree un constructor de FeedAdapter:

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

y en actividad

FeedAdapter obj = new FeedAdapter(this);

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

1
View mView;
mView.getContext();

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.