Android: видимые изображения ListView мерцают при добавлении данных в ArrayAdapter

У меня есть специальный адаптер, который расширяет ArrayAdapter, он реализует шаблоны держателей для отображения данных (текст + изображение) из веб-службы.

для отложенной загрузки изображений я использую шаблон асинхронных задач из продвинутого обучения в Android'есайт разработчиков,

Я также использую кэш диска RAM + RAM.

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

проблема в том, что при добавлении этих новых данных некоторые видимые изображения изменяются и сразу же возвращаются обратно, что приводит к странному мерцанию.

кроме этого все работает нормально, а прокрутка плавная.

насколько я понимаю, эти изменения изображения происходят при обновлении видимых видов при добавлении новых данных.

Есть ли способ обойти это нежелательное поведение?

это класс, выполняющий загрузку и управление асинхронными задачами}

public class ImageDownloader {
private ImageCache mCache;
private int reqWidth;
private int reqHeight;

public void download(String url, ImageView imageView, ImageCache imageCache, int reqHeight, int reqWidth) {
    mCache = imageCache;
    this.reqHeight = reqHeight;
    this.reqWidth = reqWidth;

    if (cancelPotentialDownload(url, imageView)) {
        BitmapDownloaderTask task = new BitmapDownloaderTask(imageView);

        DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
        imageView.setImageDrawable(downloadedDrawable);
        task.execute(url);
    }
}

private class BitmapDownloaderTask extends AsyncTask {
    private String url;
    private WeakReference imageViewReference;

    public BitmapDownloaderTask(ImageView imageView) {
        imageViewReference = new WeakReference(imageView);
    }

    @Override
    protected Bitmap doInBackground(String... strings) {
        Bitmap bitmap = null;
        try {
            bitmap =  mCache.getBitmapFromURL(strings[0], reqWidth, reqHeight);
        } catch (IOException e) {
        }

        return bitmap;
    }

    @Override
    protected void onPostExecute(Bitmap bitmap) {
        if (isCancelled()) bitmap = null;

        if (imageViewReference != null) {
            ImageView imageView = imageViewReference.get();
            BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

            if (imageView != null) {
                imageView.setImageBitmap(bitmap);
            }
        }
    }
}

private static class DownloadedDrawable extends ColorDrawable {
    private WeakReference bitmapDownloaderTaskReference;

    public DownloadedDrawable(BitmapDownloaderTask bitmapDownloaderTask) {
        bitmapDownloaderTaskReference = new WeakReference(bitmapDownloaderTask);
    }

    public BitmapDownloaderTask getBitmapDownloaderTask() {
        return bitmapDownloaderTaskReference.get();
    }
}

private static BitmapDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
    if (imageView != null) {
        Drawable drawable = imageView.getDrawable();
        if (drawable instanceof DownloadedDrawable) {
            DownloadedDrawable downloadedDrawable = (DownloadedDrawable)drawable;
            return downloadedDrawable.getBitmapDownloaderTask();
        }
    }
    return null;
}

private static boolean cancelPotentialDownload(String url, ImageView imageView) {
    BitmapDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);

    if (bitmapDownloaderTask != null) {
        String bitmapUrl = bitmapDownloaderTask.url;
        if ((bitmapUrl == null) || (!bitmapUrl.equals(url))) {
            bitmapDownloaderTask.cancel(true);
        } else {
            return false;
        }
    }
    return true;
}

это адаптер:

закрытый класс PlaceAdapter extends ArrayAdapter {final int viewResourceId;

    public PlaceAdapter(Context context, int textViewResourceId, List objects) {
        super(context, textViewResourceId, objects);
        viewResourceId = textViewResourceId;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        if (convertView == null) {
            LayoutInflater inflater = getLayoutInflater();
            convertView = inflater.inflate(viewResourceId, null);

            holder = new ViewHolder(convertView);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        PlaceModel place = getItem(position);

        holder.name.setText(place.getName());
        holder.address.setText(place.getVicinity());
        holder.position = position;

        if (place.getIcon() != null) {
            String url = mImageViewUrls.get(holder.image);
            if (url == null || (url != null && !url.equals(place.getIcon()))) {
                mDownloader.download(place.getIcon(), holder.image, mCache, 100, 100);
                mImageViewUrls.put(holder.image, place.getIcon());
            }
        } else {
            holder.image.setImageBitmap(null);
            mImageViewUrls.remove(holder.image);
        }

        return convertView;
    }
}

private class ViewHolder {
    public final ImageView image;
    public final TextView name;
    public final TextView address;
    public int position;

    public ViewHolder(View row) {
        image = (ImageView) row.findViewById(R.id.placeRow_imageView);
        name = (TextView) row.findViewById(R.id.placeRow_placeName);
        address = (TextView) row.findViewById(R.id.placeRow_placeAddress);
    }
}

mImageViewUrls этоWeakHashMap что карты междуImageView и URL, поэтому избыточные вызовы асинхронных задач можно уменьшить, проверив,ImageView уже показывает требуемое изображение. без этой реализации мерцание происходит во всех видимых изображениях при изменении данных. при этом это происходит только с некоторыми изображениями.

РЕДАКТИРОВАТЬ: я пытался устранить возможные причины этой проблемы, сначала я попытался полностью обойти реализацию кэша и загрузить каждое растровое изображение из сети, затем я попытался обернуть мой адаптер с CommonsWare 's Бесконечный адаптер, и с обоими я получил один и тот же результат .. так что это оставляет только класс ImageDownloader и мой адаптер как возможные причины .. Я 'Я полностью потерян на этом.

Ответы на вопрос(4)

Ваш ответ на вопрос