Лучший способ обрабатывать несколько вызовов getView изнутри адаптера - PullRequest
13 голосов
/ 20 мая 2010

У меня есть ListView с кастомами ArrayAdapter. Каждая строка в этом ListView имеет значок и текст. Эти значки загружаются в фоновом режиме, кэшируются, а затем с помощью функции обратного вызова заменяются соответствующими ImageViews. Логика получения миниатюры из кэша или загрузки запускается при каждом запуске getView ().

Теперь, по словам Ромена Гая:

"нет абсолютно никакой гарантии на порядок, в котором getView () будет ни разу не звонил. "

Я видел, как это произошло, для строки размера два getView () вызывался шесть раз!

Как мне изменить мой код, чтобы избежать дублирования запросов thumbnail-fetch, а также для обработки повторного просмотра?

Спасибо.

Ответы [ 7 ]

14 голосов
/ 28 мая 2010

Точно, это может произойти, например, когда у вас есть

android:layout_height="wrap_content"

в вашем ListView определении. Изменение на fill_parent / match_parent позволит избежать этого.

8 голосов
/ 20 мая 2010

Из API.

public abstract View   getView  (int position, View  convertView, 
                                 ViewGroup  parent)

convertView - старый вид для повторного использования, если это возможно. Примечание. Перед использованием убедитесь, что это представление не пустое и имеет соответствующий тип. Если невозможно преобразовать это представление для отображения правильных данных, этот метод может создать новое представление.

Таким образом, если getView уже был вызван для этого конкретного индекса, то convertView будет объектом View, который был возвращен после первого вызова.

Вы можете сделать что-то вроде.

if(!(convertView instanceof ImageView)){
   convertView = new ImageView();
   //get image from whereever
} else {} // ImageView already created
1 голос
/ 22 апреля 2015

Насколько я понимаю, вам нужно использовать шаблон проектирования ViewHolder здесь. Простое использование возвращенного convertView может привести к повторному использованию предыдущего представления (в данном случае с другим назначенным изображением).

public class ImageAdapter extends ArrayAdapter<String> {

  // Image adapter code goes here.

  private ViewHolder {
    public ImageView imageView;
    public String url;
  }

  @Override
  public View getView(final int position, View convertView, ViewGroup parent) {
    View view = null;
    ViewHolder viewHolder;
    String url = getUrl(position);
    if (convertView == null) {
      // There was no view to recycle. Create a new view.
      view = inflator.inflate(R.layout.image_layout, parent, false);
      viewHolder = new ViewHolder();
      viewHolder.imageView = (ImageView) view.findViewById(R.id.image_view);
      viewHolder.url = url;
      view.setTag(viewHolder);
    } else {
      // We got a view that can be recycled.
        view = convertView;
        viewHolder = ((ViewHolder) view.getTag());
        if (viewHolder.url.equals(url)) {
          // Nothing to do, we have the view with the correct info already.
          return view;
        }
    }

    // Do work to set your imageView which can be accessed by viewHolder.imageView

    return view;
  }
}
1 голос
/ 09 июля 2013

Я испытываю ту же проблему, я изменяю layout_height listView, чтобы match_parent разрешил мою проблему.

0 голосов
/ 12 августа 2015

Мой Fragment.xml имеет ListView, настройка макета этого ListView была android: layout_height = "wrap_content" , и этот ListView будет привязан к SimpleCursorAdapter позже. Тогда у меня такая же проблема во ViewBinder будет вызываться 3 раза. Проблема решена после того, как я изменил layout_height = "wrap_content" на "95p". Я считаю, что высота "wrap_content" вызывает эту проблему. Попытка изменить ваш Fragment.xml, и я думаю, что трижды вызванная проблема больше не будет существовать.

0 голосов
/ 20 мая 2010

Создайте массив объектов ImageView в вашем адаптере и кэшируйте их, когда вы извлекаете их (из кэша или из Интернета). Например, в getView, перед тем как получить ImageView, проверьте, находится ли он уже в вашем локальном массиве, если это так, используйте его, если не извлекаете, после того, как получили хранилище в вашем локальном массиве ImageView для будущего использования.

0 голосов
/ 20 мая 2010

Лучше было бы создать объект с миниатюрой (растровым изображением) и текстом. И прочитайте миниатюру, если ее нет в объекте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...