Android BaseAdapter с LruCache Некоторые проблемы с пользовательским интерфейсом

Я пытаюсь реализовать представление списка со всеми изображениями контактов с помощью базового адаптера и LruCache. Но при длительной прокрутке на экране все изображения (соответствующие этому виду) отображаются перед установкой фактического изображения.

Например: представление списка с 5 элементами на странице, если мы прокрутили от первого контакта до 60-го, при первом просмотре просмотра списка изображения 1,6,11,16,21..51 отображаются за несколько миллими секунд до 55-го изображения Показано

Основные коды

//Adapter
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = (ImageView) convertView;
if(imageView == null){
 imageView = new ImageView(getActivity());
}    
int id =  contactId[position];
final String imageKey = String.valueOf(contactId);
final Bitmap bitmap = cache.get(imageKey);
if (bitmap != null) {
  imageView.setImageBitmap(bitmap);
} else {    
  Resources res = context.getResources();
  BitmapManager bm = new BitmapManager(imageView, res, cache);
  bm.setContext(getActivity());
  bm.execute(id);
}
return imageView;
}

BitmapManager Пост Выполнить код

@Override
protected void onPostExecute(Bitmap bitmap) {
    // TODO Auto-generated method stub
    try{
        if(isCancelled()){
            bitmap = null;
        }
        if(imageViewReference != null && bitmap != null){
            ImageView imageView = imageViewReference.get();
            imageView.setImageBitmap(bitmap);
            cache.put(String.valueOf(res), bitmap);
            if(imageView != null){
                imageView.setImageBitmap(bitmap);
            }

        }
    }catch(Exception e){

    }
    super.onPostExecute(bitmap);
}

Как решить эту проблему. Спасибо

1 ответ

Решение

По мере прокрутки вниз ваши представления повторно используются для новых позиций списка, которые появляются. Поскольку вы запускаете новую задачу BitmapManager каждый раз, когда вызывается getView, задачи выстраиваются в очередь, ожидая обновления изображения. Когда они заканчивают загрузку своего растрового изображения, они помещают его в ImageView по порядку, что вы и видите.

Похоже, вы пытались использовать ссылку на ImageView, чтобы избежать использования растрового изображения после его прокрутки вне поля зрения, но причина, по которой это не сработало, заключается в том, что адаптер перерабатывает ваши ImageViews, и поэтому ссылка остается действительной, хотя на самом деле ImageView сейчас используется для другого элемента списка.

Есть разные способы решения этой проблемы, но самое простое, что приходит на ум, - это создать свой BitmapManager с индексом списка, а не с самим ImageView. Затем в getView вы можете сохранить карту того, какие виды используются на каких позициях. Когда BitmapManager завершит работу, проверьте, существует ли текущий ImageView для позиции, которую вы только что загрузили в кэш. Если нет, то ничего не делать.

Вот код, который показывает, о чем я говорю. Я не пробовал, поэтому извиняюсь, если есть ошибки.

//Adapter
private SparseArray<ImageView> ivMap = new SparseArray<ImageView>();
public View getView(int position, View convertView, ViewGroup parent) {
    ImageView imageView = (ImageView) convertView;
    if(imageView == null){
      imageView = new ImageView(getActivity());
    } else {
      // If recycled, remove the ImageView's previous position from map
      int oldPosition = ivMap.indexOfValue(imageView);
      if (oldPosition >= 0) {
        ivMap.remove(oldPosition);
      }
    }
    // Keep track of which view is representing this position
    ivMap.put(position, imageView);

    int id =  contactId[position];
    final String imageKey = String.valueOf(contactId);
    final Bitmap bitmap = cache.get(imageKey);
    if (bitmap != null) {
      imageView.setImageBitmap(bitmap);
    } else {    
      Resources res = context.getResources();
      BitmapManager bm = new BitmapManager(ivMap, position, res, cache);
      bm.setContext(getActivity());
      bm.execute(id);
    }
    return imageView;
}

//BitmapManager
@Override
protected void onPostExecute(Bitmap bitmap) {
    // TODO Auto-generated method stub
    try{
        if(isCancelled()){
            bitmap = null;
        }
        if(bitmap != null){
            cache.put(String.valueOf(res), bitmap);
            ImageView imageView = ivMap.get(position);
            if (imageView != null) {
                imageView.setImageBitmap(bitmap);
            }
        }
    }catch(Exception e){

    }
    super.onPostExecute(bitmap);
}
Другие вопросы по тегам