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

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


person Vishnu V    schedule 11.12.2014    source источник


Ответы (1)


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

Похоже, вы пытались использовать ссылку на ImageView, чтобы избежать использования растрового изображения после того, как оно было прокручено вне поля зрения, но причина, по которой это не сработало, заключается в том, что адаптер повторно использует ваши ImageView, поэтому ссылка остается действительной, хотя на самом деле 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);
}
person Bruce    schedule 12.12.2014