Android-Universal-Image-Loader icon indicating copy to clipboard operation
Android-Universal-Image-Loader copied to clipboard

Problem with loadImage() when loading same image url

Open yisizhu520 opened this issue 8 years ago • 2 comments

There is an article detail activity with a comment list in my app. Every list item has a custom avatar view, so I use method loadImage instead of displayImage to load image from network or cache. When the comment avatar views load the image with the same url (the same user posts many comments), only part of views can display the image.

yisizhu520 avatar Aug 02 '16 00:08 yisizhu520

I found the reason in class DisplayBitmapTask

@Override
    public void run() {
        if (imageAware.isCollected()) {
            L.d(LOG_TASK_CANCELLED_IMAGEAWARE_COLLECTED, memoryCacheKey);
            listener.onLoadingCancelled(imageUri, imageAware.getWrappedView());
        } else if (isViewWasReused()) {
            L.d(LOG_TASK_CANCELLED_IMAGEAWARE_REUSED, memoryCacheKey);
            listener.onLoadingCancelled(imageUri, imageAware.getWrappedView());
        } else {
            L.d(LOG_DISPLAY_IMAGE_IN_IMAGEAWARE, loadedFrom, memoryCacheKey);
            displayer.display(bitmap, imageAware, loadedFrom);
            engine.cancelDisplayTaskFor(imageAware);
            listener.onLoadingComplete(imageUri, imageAware.getWrappedView(), bitmap);
        }
    }

when the first thread finished the load task, it will call engine.cancelDisplayTaskFor(imageAware)

void cancelDisplayTaskFor(ImageAware imageAware) {
    cacheKeysForImageAwares.remove(imageAware.getId());
}

So when the other thread loaded the image from cache or network and go to the DisplayBitmapTask, the condition isViewWasReused() method return false because the record in map cacheKeysForImageAwares has been removed by the first thread with the same ImageAware id.

/** Checks whether memory cache key (image URI) for current ImageAware is actual */
    private boolean isViewWasReused() {
        String currentCacheKey = engine.getLoadingUriForView(imageAware);
        return !memoryCacheKey.equals(currentCacheKey);
    }

loadImage method use NonViewAware to reuse the logic of displayImage. But the getId() return the hashcode of the image url instead of its hashcode.

    @Override
    public int getId() {
        return TextUtils.isEmpty(imageUri) ? super.hashCode() : imageUri.hashCode();
    }

It's the reason causing the bug. I don't know the benifit using imageUri.hashCode();. But following code is fine

    @Override
    public int getId() {
        return super.hashCode();
    }

yisizhu520 avatar Aug 02 '16 01:08 yisizhu520

this bug still alive!

dann1609 avatar Oct 12 '18 10:10 dann1609