-
Notifications
You must be signed in to change notification settings - Fork 6.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OOM callback #859
Comments
seems to be related to #491 |
Yes... the problem with delegating OOM to |
Edit: since #1057 was merged to 3.8.0 this is no longer required. OOMs are delegated as load failures, you can check for them with Sorry, not custom loader, custom decoder: class OOMReadyStreamBitmapDecoder extends StreamBitmapDecoder {
public OOMReadyStreamBitmapDecoder(Context context) {
super(context);
} // or any other ctor you want from super
@Override public Resource<Bitmap> decode(InputStream source, int width, int height) {
try {
return super.decode(source, width, height);
} catch (OutOfMemoryError err) {
throw new RuntimeException(err);
}
}
} and then just use it: String url = "https://upload.wikimedia.org/wikipedia/commons/c/c6/BlankMap-World-large3.png";
BitmapRequestBuilder<String, Bitmap> oomRequest = Glide
.with(context)
.fromString()
.asBitmap()
.imageDecoder(new OOMReadyStreamBitmapDecoder(context))
//.cacheDecoder(new FileToStreamDecoder<>(new OOMReadyStreamBitmapDecoder(context))) // needed for .diskCacheStrategy(SOURCE|ALL)
//.error(R.drawable.ic_launcher) // displayed when OOM (because throw RuntimeException)
//.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) // to make sure it OOMs (url is huge)
;
oomRequest
.load(url)
.listener(new RequestListener<String, Bitmap>() {
@Override public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {
if (e.getCause() instanceof OutOfMemoryError) {
// do something (you also have model available)
// if you return true, .error() won't be displayed
}
return false;
}
@Override public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
return false;
}
})
; or oomRequest
.load(url)
.into(new BitmapImageViewTarget(imageView) {
@Override public void onLoadFailed(Exception e, Drawable errorDrawable) {
if (e.getCause() instanceof OutOfMemoryError) {
// do something
}
super.onLoadFailed(e, errorDrawable);
}
})
; It's not a global solution, you can do this for any load separately. |
cool it works, thanks a lot for the fast reply. Imho it should be the default behaviour, an exception should call onLoadFailed too. If Im loading the bitmap into GlideDrawableImageViewTarget, the onLoadFaileds' first parameter is an Exception so it should be there. |
doesn't this happen if you have an |
oh ye really, out of memory is an error, not an exception. It makes sense now. Im using the fourth code block you wrote with BitmapImageViewTarget , not the listener one. Works fine now, I can catch the oom in onLoadFailed. Thanks a lot for the trick, guess the issue can be closed. |
Hello guys, I've found this solution very helpful. However, there are some cases where ( specially in devices with very low memory capabilities ) I can't catch the OOM Exception. The app does not crash but I can't do what's necessary when an exception like this comes out. Another comment about the solution that you proposed. In those lines of code if (e.getCause() instanceof OutOfMemoryError) {
// do something
} In some cases 'e' is null and the method getCause() could return null too. It should be checked. |
I guess you're not asking for A quick "Analyze data flow to here" with "Group by leaf expression" in IDEA on
Going deeper into Edit: I just noticed that transformation or transcoder can also throw an OOM which is uncaught so you'll need to wrap |
Hey @TWiStErRob , I've been trying to follow this advice to come up with a decoder for a ResourceDecoder decoder = new GifBitmapWrapperResourceDecoder(
new ImageVideoBitmapDecoder(new StreamBitmapDecoder(context), new FileDescriptorBitmapDecoder(context)) {
@Override
public Resource<Bitmap> decode(ImageVideoWrapper source, int width, int height) throws IOException {
try {
return super.decode(source, width, height);
} catch (OutOfMemoryError e) {
throw new RuntimeException("OOM when loading GIF");
}
}
},
new GifResourceDecoder(context) {
@Override
public GifDrawableResource decode(InputStream source, int width, int height) {
try {
return super.decode(source, width, height);
} catch (OutOfMemoryError e) {
throw new RuntimeException("OOM when loading GIF");
}
}
}, Glide.get(context).getBitmapPool()); I'm then setting these as |
@mcoded There was a reason I used You seem to be really close, but you forgot to subclass the most important one: Try: GifBitmapWrapperResourceDecoder decoder = ...;
...
.decoder(decoder)
.cacheDecoder(new FileToStreamDecoder<>( // from ImageVideoGifDrawableLoadProvider
new GifBitmapWrapperStreamResourceDecoder(decoder))) Declare Tip: Subscribe to #1057 so you know when you can get rid of these constructs. |
Thanks for the pointers, works great now :) |
@TWiStErRob I've been seeing a few complaints (via Leak Canary) of memory leaks since putting in the decoders mentioned earlier, particularly due to
|
@mcoded it looks like your resources are kept in memory cache, which is a good thing, but to hit the cache all the decoders are also kept within This is also probably a bug in |
@TWiStErRob you wrote about catching OOM for Glide v3 and I just wonder how to do that in v4. StreamBitmapDecoder quite changed |
Hello, Im sometimes loading very huge images, so out of memory on some devices is common. Its not a huge issue, but Id like to react on it. Is there any callback for Out of memory, or any way to find it out? Shouldnt onLoadFailed be called if some exception is thrown? I can create a workaround with onResourceReady and some timer to check if the image was loaded properly, but Id like some nicer solution. So how should I react to the internal Glide Out of memory exception?
The text was updated successfully, but these errors were encountered: