Пикассо загружается в неправильное изображение при использовании шаблона владельца
Я пытаюсь использовать библиотеку Picasso для загрузки внешних изображений в строки в ListView
. У меня есть пользовательский ArrayAdapter
следующим образом:
public class RevisedBusinessesAdapter extends ArrayAdapter<HashMap<String, String>> {
Context context;
int layoutResourceId;
ArrayList<HashMap<String, String>> data = null;
public RevisedBusinessesAdapter(Context context, int layoutResourceId, ArrayList<HashMap<String, String>> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
RevisedBusinessHolder holder = null;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new RevisedBusinessHolder();
holder.ivLogo = (ImageView) row.findViewById(R.id.ivBusinessLogo);
row.setTag(holder);
} else {
holder = (RevisedBusinessHolder) row.getTag();
}
HashMap<String, String> business = data.get(position);
String strLogoURL = business.get("logoURL");
if (null != strLogoURL && !"".equals(strLogoURL)) {
Picasso.with(this.context).load(strLogoURL).into(holder.ivLogo);
}
return row;
}
static class RevisedBusinessHolder {
ImageView ivLogo;
}
}
где logoURL - это URL-адрес удаленного изображения; если не указано, ivBusinessLogo
имеет локальный набор src, и это показано вместо этого. Когда я быстро прокручиваю, Picasso загружает изображение в неправильное ImageView
, и я заканчиваю его несколькими копиями в списке.
Ответ на этот предполагает добавить
Picasso.with(context).cancelRequest(holder.ivLogo);
до существующего вызова Пикассо, но это не имеет никакого значения. Если я удалю проверку row == null
и всегда создаю новое представление, оно работает нормально. В полной версии этого, однако, есть также четыре текстовых изображения и пять других изображений (маленькие значки, загруженные из локальных ресурсов, а не через Picasso), которые необходимо обновлять в каждом getView
.
Есть ли способ сделать эту работу с шаблоном View Holder Документация по Android рекомендует?
Ответы
Ответ 1
Вы всегда должны вызывать Picasso, даже если ваш URL null
. Таким образом, он знает, что изображение было переработано.
Удалить этот оператор if
:
if (null != strLogoURL && !"".equals(strLogoURL)) {
Вы также должны рассмотреть возможность использования образа-заполнителя или изображения с ошибкой, чтобы что-то отображалось, когда нет URL-адреса.
Если вы настаиваете на сохранении инструкции if
(но вы этого не должны!), вам нужно сказать Пикассо, что просмотр изображения был переработан, вызвав cancelRequest
:
Picasso.with(this.context).cancelRequest(holder.ivLogo);
Ответ 2
Установленный по умолчанию набор атрибутов src в layout.xml(в ImageView) переопределяется последним кэшированным файлом dowload, если текущий элемент не имеет изображения для загрузки с URL-адреса.
Вы должны вручную установить по умолчанию для itens, у которых нет атрибута изображения:
try {
Picasso.with(activity.getApplicationContext()).load(customer.getImage().getPath()).placeholder(R.drawable.image_placeholder)
.error(R.drawable.image_placeholder).into(imageView);
}
catch (Exception e) {
imageView.setImageResource(R.drawable.default_customer_icon);
// this set the default img source if the path provided in .load is null or some error happened on download.
}
Ответ 3
У меня такая же проблема и исправлена. Пожалуйста, рассмотрите параметр convertView в методе getView
convertView - это старый вид для повторного использования, если это возможно. Примечание. Вы должны проверить что перед просмотром это представление не имеет значения null и соответствующего типа. Если невозможно преобразовать это представление для отображения правильных данных, этот метод может создать новое представление.
Когда вы используете держатель, Picasso будет загружать изображение в образное изображение строки и повторное его использование. Вот почему вы видите дублирующее изображение.
И, на мой взгляд, вы должны загружать свое изображение, пока создается первый вид строки. Попробуйте изменить свой код на
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new RevisedBusinessHolder();
ImageVIew ivLogo = (ImageView) row.findViewById(R.id.ivBusinessLogo);
Picasso.with(this.context).load("Your Image URL").into(holder.ivLogo);
row.setTag(holder);
}
Ответ 4
Добавьте инструкцию else после оператора Picasso.with(). load(). в(). Добавьте else holder.ivLogo.setImageBitmap(null);
. Или используйте растровое изображение заполнителя.
Увидев решение Octa George, лучше всегда выполнять holder.ivLogo.setImageBitmap(placeholderbitmap);
перед вызовом Picasso. В противном случае, когда Пикассо "не спешит", вы сначала увидите неправильное переработанное изображение.