Cara mendapatkan konteks dalam adaptor tampilan pendaur ulang


129

Saya mencoba menggunakan pustaka picasso untuk dapat memuat url ke imageView, tapi saya tidak bisa contextmenggunakan pustaka picasso dengan benar.

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

}

Jawaban:


290

Anda memiliki beberapa opsi di sini:

  1. Lulus Contextsebagai argumen untuk FeedAdapter dan simpan sebagai bidang kelas
  2. Gunakan injeksi ketergantungan untuk menyuntikkan Contextsaat Anda membutuhkannya. Saya sangat menyarankan membaca tentang itu. Ada alat yang bagus untuk itu - Dagger by Square
  3. Dapatkan dari Viewobjek apa pun . Dalam kasus Anda, ini mungkin cocok untuk Anda:

    holder.pub_image.getContext()

    Apa pub_imageadanya ImageView.


64
Saya lebih suka opsi ketiga, mendapatkan konteks dari tampilan. Ini adalah solusi paling sederhana dan paling mudah.
Dick Lucas

atau, jauh lebih baik, meneruskan instance Picasso, daripada memegang instance Picasso pada instance kelas dan memuatnya dengan malas.
Eric Cochran

8
Setiap ViewHolder berisi instance itemView yang Anda berikan dalam konstruktor. Gunakan yang seperti ini: itemView.getContext ()
Andrei Lupsa

1
Anda tidak dapat melakukan # 2, bukan? Saya sudah mencobanya, tetapi ini akan menjadi milik Anda ApplicationContextdan tidak terkait dengan aktivitas, yang menyebabkan crash runtime dari dalam Glide.
boltup_im_coding

bagaimana cara melewatkan objek komponen ke adaptor jika saya ingin menggunakan # 2?
Ezio

32

Anda dapat menambahkan variabel global:

private Context context;

kemudian tetapkan konteksnya dari sini:

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

Selamat Codding :)


Bekerja untuk saya juga! Terima kasih
Kenny Dabiri

21
Saya sangat menyarankan MELAWAN memiliki referensi global untuk Konteks. Ini bisa menyebabkan masalah kebocoran memori yang mengerikan !!
solidak

1
jika Anda subclass viewholder, itu bisa menjadi pribadi.
r3dm4n

Jika adaptor terpasang ke RecyclerView maka konteks itu dijamin akan tetap dibutuhkan. Jika Anda dapat melepas adaptor, maka itu masih baik-baik saja kecuali karena alasan tertentu Anda memegang referensi kuat untuk adaptor ini setelah terlepas, dalam hal ini Anda harus menghapus konteks cache, ada metode suka onDetachedFromRecyclerViewatau sesuatu.
androidguy

19

Jawaban singkat:

Context context;

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

Penjelasan mengapa jawaban lain tidak bagus:

  1. Melewati Contextke adaptor sama sekali tidak perlu, karena RecyclerViewAnda dapat mengaksesnya dari dalam kelas
  2. Mendapatkan Contextdi ViewHolderberarti tingkat yang Anda lakukan setiap kali Anda mengikat atau membuatViewHolder . Anda menduplikasi operasi.
  3. Saya tidak berpikir Anda perlu khawatir tentang kebocoran memori. Jika adaptor Anda tertinggal di luar Activitymasa hidup Anda (yang akan aneh), maka Anda sudah memiliki kebocoran.

Dalam hal ini, haruskah kita menerapkan onDetachedFromRecyclerView()dan melepaskan konteks?
John Pang

@JohnPang tidak benar-benar kecuali Anda ingin menjadi sangat defensif. Jika Anda menyimpan referensi adaptor dalam Aktivitas, Anda aman.
Maciej Beimcik

17

Anda dapat menggunakan konteks 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);


}

6

Anda dapat mendefinisikan:

Context ctx; 

Dan di onCreateinisialisasi ctxke:

ctx=parent.getContext(); 

Catatan: Induk adalah ViewGroup.


5

Pertama secara global mendeklarasikan

Context mContext;

lewat konteks dengan konstruktor, dengan memodifikasinya.

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

kemudian gunakan di mContextmana pun Anda membutuhkannya


5

Anda dapat menggunakan seperti ini view.getContext ()

Contoh

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

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


        }
    });


4

Buat konstruktor FeedAdapter:

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

dan dalam Aktivitas

FeedAdapter obj = new FeedAdapter(this);

2

Pertama, tambahkan variabel global

Context mContext;

Kemudian ubah konstruktor Anda menjadi ini

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

Lewati konteks Anda saat membuat adaptor.

FeedAdapter myAdapter = new FeedAdapter(this,myDataset);

1
View mView;
mView.getContext();

Sementara kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah akan sangat membantu untuk meningkatkan kualitas posting Anda, dan mungkin menghasilkan lebih banyak suara. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang. Harap edit jawaban Anda untuk menambahkan penjelasan dan berikan indikasi tentang batasan dan asumsi apa yang berlaku. Dari Ulasan
double-beep
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.