Як отримати контекст у адаптері перегляду утилізатора


129

Я намагаюся використовувати бібліотеку picasso, щоб мати можливість завантажувати URL до imageView, але я не в змозі contextправильно використати бібліотеку пікассо.

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

}

Відповіді:


290

Тут у вас є кілька варіантів:

  1. Передайте Contextяк аргумент FeedAdapter і зберігайте його як поле класу
  2. Використовуйте ін'єкційну залежність для ін'єкцій, Contextколи вам це потрібно. Я настійно пропоную прочитати про це. Для цього є чудовий інструмент - Dagger by Square
  3. Отримайте його від будь-якого Viewоб’єкта. У вашому випадку це може працювати для вас:

    holder.pub_image.getContext()

    Як pub_imageце ImageView.


64
Я віддаю перевагу третьому варіанту, отримуючи контекст з точки зору. Це найпростіше і найпростіше рішення.
Дік Лукас

або, що ще краще, передати в екземпляр Picasso, а не тримати екземпляр Picasso в екземплярі класу та ледаче завантажувати його.
Ерік Кокран

8
Кожен ViewHolder містить екземпляр itemView, який ви передаєте в конструктор. Скористайтеся таким: itemView.getContext ()
Андрій Лупса

1
Ви не можете зробити №2, чи не так? Я спробував це, але це в кінцевому підсумку буде вашим ApplicationContextі не пов'язане з діяльністю, що призведе до аварії виконання зсередини Glide.
boltup_im_coding

як передати компонентний об’єкт адаптеру у випадку, якщо я хочу використовувати №2?
Еціо

32

Ви можете додати глобальну змінну:

private Context context;

потім призначте контекст звідси:

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


Працював і для мене! Дякую
Кенні Дабірі

21
Я настійно пропоную ПРОТИ мати глобальні посилання на Context. Це може призвести до жахливих проблем з витоком пам'яті !!
солідак

1
якщо ви переглядаєте підклас переглядача, він може бути приватним.
r3dm4n

Якщо адаптер приєднаний до RecyclerView, тоді цей контекст гарантовано потрібен. Якщо ви не можете приєднати адаптер, то це все одно добре, якщо з якоїсь причини ви чітко не посилаєтесь на цей адаптер після його від'єднання, і в такому випадку вам слід очистити кешований контекст, є такий метод, як onDetachedFromRecyclerViewчи щось.
androidguy

19

Коротка відповідь:

Context context;

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

Пояснення, чому інші відповіді не великі:

  1. Перехід Contextдо адаптера абсолютно непотрібний, оскільки RecyclerViewви можете отримати доступ до нього зсередини класу
  2. Отримання Context на ViewHolderрівні означає, що ви робите це кожен раз, коли зв'язуєте чи створюєте ViewHolder. Ви дублюєте операції.
  3. Я не думаю, що вам не потрібно турбуватися про якісь витоки пам'яті. Якщо ваш адаптер затримався поза вашим Activityтерміном експлуатації (що було б дивно), то у вас вже є витік.

Чи будемо ми реалізувати onDetachedFromRecyclerView()та випустити контекст у цьому випадку ?
Джон Панг

@JohnPang насправді, якщо ви не хочете бути надзвичайно захисними. Якщо ви зберігаєте посилання адаптера в межах діяльності, ви в безпеці.
Maciej Beimcik

17

Ви можете використовувати 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);


}


5

Спочатку заявляйте глобально

Context mContext;

передайте контекст конструктору, модифікуючи його.

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

то використовуйте те, mContextде вам це потрібно


5

Ви можете використовувати такий view.getContext ()

Приклад

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

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


        }
    });


4

Створіть конструктор FeedAdapter:

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

та в діяльності

FeedAdapter obj = new FeedAdapter(this);

2

Спочатку додайте глобальну змінну

Context mContext;

Потім змініть свій конструктор на це

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

Передайте свій контекст під час створення адаптера.

FeedAdapter myAdapter = new FeedAdapter(this,myDataset);

1
View mView;
mView.getContext();

Хоча цей код може вирішити питання, включаючи пояснення, як і чому це вирішує проблему, справді допоможе покращити якість вашої публікації та, ймовірно, призведе до збільшення кількості голосів. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, а не лише про людину, яка зараз задає питання. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються. З огляду
подвійний звуковий сигнал
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.