Como obter um contexto em um adaptador de exibição de reciclador

129

Estou tentando usar a biblioteca do picasso para carregar o url no imageView, mas não consigo contextusar a biblioteca do picasso corretamente.

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

}
Estranho B.
fonte

Respostas:

290

Você tem algumas opções aqui:

  1. Passe Contextcomo argumento para o FeedAdapter e mantenha-o como campo de classe
  2. Use injeção de dependência para injetar Contextquando precisar. Eu sugiro fortemente a leitura sobre isso. Existe uma ótima ferramenta para isso - Dagger by Square
  3. Obtê-lo de qualquer Viewobjeto. No seu caso, isso pode funcionar para você:

    holder.pub_image.getContext()

    Como pub_imageé um ImageView.

pelotasplus
fonte
64
Prefiro a terceira opção, obtendo o contexto da visualização. É a solução mais simples e direta.
Dick Lucas
ou, muito melhor, passe na instância do Picasso, em vez de manter uma instância do Picasso na instância da classe e carregá-la com preguiça.
Eric Cochran
8
Cada ViewHolder contém uma instância do itemView que você transmite no construtor. Use esse como este: itemView.getContext () #
Andrei Lupsa
1
Você não pode fazer o segundo, pode? Eu tentei isso, mas isso acabará sendo seu ApplicationContexte não estará vinculado à atividade, levando a uma falha de tempo de execução no Glide.
Boltup_im_coding 5/0318
como passar o objeto componente para o adaptador caso eu queira usar o número 2?
Ezio
32

Você pode adicionar variável global:

private Context context;

em seguida, atribua o contexto a partir daqui:

@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
fonte
Trabalhou para mim também! Graças
Kenny Dabiri
21
Eu sugiro fortemente CONTRA ter referências globais ao contexto. Isso pode levar a problemas horríveis de vazamento de memória!
21917 solidak
1
se você subclassificar o visualizador, ele poderá ser privado.
R3dm4n
Se o adaptador estiver conectado a um RecyclerView, esse contexto certamente será necessário. Se você pode desanexar o adaptador, ainda assim está bom, a menos que, por algum motivo, tenha uma forte referência a esse adaptador depois que ele foi desconectado; nesse caso, você deve limpar o contexto em cache, existe um método como esse onDetachedFromRecyclerView.
precisa saber é o seguinte
19

Resposta curta:

Context context;

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

Explicação por que outras respostas não são ótimas:

  1. Passar Contextpara o adaptador é completamente desnecessário, pois RecyclerViewvocê pode acessá-lo de dentro da classe
  2. Obter Contextno ViewHoldernível significa que você faz isso toda vez que liga ou cria um ViewHolder. Você duplica operações.
  3. Acho que você não precisa se preocupar com nenhum vazamento de memória. Se o seu adaptador permanecer fora da sua Activityvida útil (o que seria estranho), você já terá um vazamento.
Maciej Beimcik
fonte
Nesse caso, devemos implementar onDetachedFromRecyclerView()e liberar contexto?
John Pang
@JohnPang não, a menos que você queira ser extremamente defensivo. Se você mantiver a referência do adaptador dentro da Atividade, estará seguro.
Maciej Beimcik
17

Você pode usar o contexto pub_image ( 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
fonte
6

Você pode definir:

Context ctx; 

E na onCreateinicialização ctxpara:

ctx=parent.getContext(); 

Nota: Pai é um ViewGroup.

Marcos vitouley
fonte
5

Primeiro declarar globalmente

Context mContext;

passe o contexto com o construtor, modificando-o.

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

depois use o local mContextque precisar

Blue_Alien
fonte
5

Você pode usar como este view.getContext ()

Exemplo

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

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


        }
    });
Arpit Patel
fonte
5

você pode usar isso:

itemView.getContext()
张家 宝
fonte
4

Crie um construtor do FeedAdapter:

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

e em atividade

FeedAdapter obj = new FeedAdapter(this);
Blockwala
fonte
2

Primeiro adicione uma variável global

Context mContext;

Então mude seu construtor para este

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

A passagem do seu contexto ao criar o adaptador.

FeedAdapter myAdapter = new FeedAdapter(this,myDataset);
AKT
fonte
1
View mView;
mView.getContext();
Rohit Daftari
fonte
Embora esse código possa resolver a questão, incluindo uma explicação de como e por que isso resolve o problema realmente ajudaria a melhorar a qualidade da sua postagem e provavelmente resultará em mais votos positivos. Lembre-se de que você está respondendo à pergunta dos leitores no futuro, não apenas à pessoa que está perguntando agora. Por favor edite sua resposta para adicionar explicações e dar uma indicação do que limitações e premissas se aplicam. Da avaliação
double-beep