Glide: Accessing error/placeholder bitmaps is not (?) possible

Created on 2 Apr 2016  路  3Comments  路  Source: bumptech/glide

Issue/Question
I've been trying to implement basic image displaying with Glide, but it seems like it only returns the bitmap if the image passed to the ".load" method could be loaded successfully. Displaying the error drawable wouldn't cause Glide to notify the callback method defined in the RequestListener and passing the error bitmap, but the onException method (returning nothing valuable for me). For example this prevents me from being able to generate a Palette from an error image.

Glide Version:
How I added Glide to my project:

compile 'com.github.bumptech.glide:glide:3.7.0'

Additional dependencies
The library I use can be found here : https://github.com/wasabeef/glide-transformations

Device/Android Version
I've already tried the code on an emulated Nexus 6P (Android 6.0), emulated Nexus 5x (Android 6.0) and a real Samsung Galaxy S3 LTE running version Android 4.3.

What I do in the classes
First of all, sorry for the terrible formatting.

Glide
     .with(getActivity())
     .load(uri)
     .asBitmap()
     .transform(newCropCircleTransformation(getActivity()))
     .error(R.drawable.movie_error_drawable)
     .into(movieHolder.art);

CropCircleTransformation is a part of the library I mentioned above.
This is what I also tried as a temporary solution:

Glide
    .with(getActivity())
    .load(uri)
    .asBitmap()
    .transform(new CropCircleTransformation(getActivity()))
    .listener(new RequestListener<Uri, Bitmap>() {

        @Override
        public boolean onException(Exception e, Uri model, Target<Bitmap> target, boolean isFirstResource) {

            // I load the movie error drawable in the onException method, 
            // so even the error drawable will be rounded!
            Glide
                    .with(getActivity())
                    .load(R.drawable.movie_error_drawable)
                    .asBitmap()
                    .transform(new CropCircleTransformation(getActivity()))
                    .into(movieHolder.art);

            return false;
        }

        @Override
        public boolean onResourceReady(Bitmap resource, Uri model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
            return false;
        }
    })
    .into(movieHolder.art);

It was intended to be a really hackish way to get the error drawable bitmap. There are still problems even with this "solution". Sometimes the image, loaded in the onException method doesn't get transformed (I never get a rounded view) and in most cases it doesn't even get loaded!

Last words
How can I achieve the desired thing (without hacking)?

question

Most helpful comment

Lot of things were mentioned so I'll just write bullets:

  • You cannot access the Drawable passed to .error or .placeholder as a Bitmap without hacking
  • What you observed is the intended behavior, look into the Target interface (BitmapImageViewTarget is the impl you're getting) to see how the error (onLoadFailed) and placeholder (onLoadStarted/onLoadCleared) Drawable is being handled. RequestListener is just peeking at what's happening, the real deal is Target.
  • Your workaround to get the drawable is actually not bad, I didn't think of this before. It's worth noting that it only works with real bitmaps (#350) and DPI is ignored (see conversation starting at https://github.com/bumptech/glide/issues/591#issuecomment-193443665)
  • You should be able to see why it only works sometimes to load from onException if you understand this https://github.com/bumptech/glide/issues/913#issuecomment-181099468
    But, you may be able to get it work if you return true after the load. If that doesn't work either you can try to post a new load with movieHolder.art.post(() -> Glide.with...). This may be needed because these interaction with the user (you) are on the UI thread, so ordering must be handled correctly.
  • You can find more information about why placeholder and error is not transformed in #317 and linked issues, latest being #1077 where I gave a reasonable workaround. Also note that you should calculate palette colors only once per R.drawable.x and cache it, those values may only change per release. You can even persist the colors in DB or preferences (just don't forget to clear them on each release because IDs may change: SQLiteOpenHelper.onUpgrade is a good callback to clear in as it's called once per update, if you bump the DB version with the versionCode)
  • Your formatting and detailed description is actually in the top 5% here...

Have a nice read of linked issues.

All 3 comments

Lot of things were mentioned so I'll just write bullets:

  • You cannot access the Drawable passed to .error or .placeholder as a Bitmap without hacking
  • What you observed is the intended behavior, look into the Target interface (BitmapImageViewTarget is the impl you're getting) to see how the error (onLoadFailed) and placeholder (onLoadStarted/onLoadCleared) Drawable is being handled. RequestListener is just peeking at what's happening, the real deal is Target.
  • Your workaround to get the drawable is actually not bad, I didn't think of this before. It's worth noting that it only works with real bitmaps (#350) and DPI is ignored (see conversation starting at https://github.com/bumptech/glide/issues/591#issuecomment-193443665)
  • You should be able to see why it only works sometimes to load from onException if you understand this https://github.com/bumptech/glide/issues/913#issuecomment-181099468
    But, you may be able to get it work if you return true after the load. If that doesn't work either you can try to post a new load with movieHolder.art.post(() -> Glide.with...). This may be needed because these interaction with the user (you) are on the UI thread, so ordering must be handled correctly.
  • You can find more information about why placeholder and error is not transformed in #317 and linked issues, latest being #1077 where I gave a reasonable workaround. Also note that you should calculate palette colors only once per R.drawable.x and cache it, those values may only change per release. You can even persist the colors in DB or preferences (just don't forget to clear them on each release because IDs may change: SQLiteOpenHelper.onUpgrade is a good callback to clear in as it's called once per update, if you bump the DB version with the versionCode)
  • Your formatting and detailed description is actually in the top 5% here...

Have a nice read of linked issues.

Thank you so much. I'll have to look after a lot of things, so I hope I can create an acceptable solution.

Feel free create new issues if you have specific problems that are not covered by the links.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

r4m1n picture r4m1n  路  3Comments

technoir42 picture technoir42  路  3Comments

sant527 picture sant527  路  3Comments

billy2271 picture billy2271  路  3Comments

piedpiperlol picture piedpiperlol  路  3Comments