Hi there, I'm using Glide in my recyclerview adapter as you provided in sample app.
I want to round top corners of image, but now, I'm using this way that round all corners:
mGlide.load(post.Image.ImageLow.ImageUrl)
.asBitmap()
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.priority(Priority.IMMEDIATE)
.override(calculateWidth(post), calculateHeight(post))
.into(new BitmapImageViewTarget(holder.POST_IMAGE) {
@Override protected void setResource(Bitmap resource) {
RoundedBitmapDrawable roundImage = RoundedBitmapDrawableFactory.create(mActivity.getResources(), resource);
roundImage.setCornerRadius(Utils.dpToPx(3, mActivity));
holder.POST_IMAGE.setImageDrawable(roundImage);
}
});
Is there any default transformation to do that in Glide library?
I have a bad experience of using glide-transformations for this , this made my recyclerview so Laggy :(
I think that support lib class doesn't support that.
Glide doesn't have anything built in except for the BitmapTransformation base class.
In there you can go wild as @wasabeef demonstrated.
If you don't want to use that lob you can roll your own, just extend the above mentioned class (see his lib or Glide's CenterCrop/FitCenter for example, and read the docs in the source code).
Also see http://stackoverflow.com/a/24737726/253468 for an algorithm.
Btw, I think you got laggy from using a transformation, not because you used that library. If your override calculates a too big size that can be a culprit, also make sure you're using the latest Glide; and remove that skipMemoryCache call and make sure the calculate* methods return consistent values to speed up scrolling: 1px difference in there can mean bad behaviour.
I'm using Glide 3.7.0
Let me show you, what I'm doing in my calculate method. I've a staggered recyclerview like pinterest app ( this is mine / As you can see all corners are rounded by this method ):

for determine and set width and height to ImageView before image load by glide, I calculate them by these information:
java
screenWidth = Utils.getScreenWidth((Activity) mActivity);
minusWidth = Utils.dpToPx(12, mActivity);
realWidth = (screenWidth / 2) - minusWidth;
java
int ImageWidth = currentPost.Image.ImageLow.ImageWidth;
int ImageHeight = currentPost.Image.ImageLow.ImageHeight;
java
int mNewWidth = (int) Math.ceil(realWidth);
int mNewHeight = (ImageHeight*mNewWidth) / ImageWidth;
java
LayoutParams params = new LayoutParams(calculateWidth(currentPost), calculateHeight(currentPost));
holder.POST_IMAGE.setLayoutParams(params);
I. Is this strategy wrong?
II. why should remove skipMemoryCache?
I. Is this strategy wrong?
Not necessarily if you're happy with it, but there are ways to let the Android View system do the layout calculations for you and Glide would pick that value up. All you need is the aspect ratio of the source image (no hardcoded margins and getting screen size). See https://github.com/TWiStErRob/glide-support/blob/master/src/glide3/java/com/bumptech/glide/supportapp/github/_864_staggered_grid/FeedEntryViewHolder.java#L55
II. why should remove skipMemoryCache?
When you scroll down and then back up your images are being reloaded from the disk again and again, if you just scroll back and forth you shouldn't see the placeholder/empty space not even for a millisecond because memory cache loads in Glide are synchronous. Same applies for backing out an activity and opening it again. Newer devices have hundreds of megabytes available to JVMs which can be filled with these cached Bitmaps. Just out of curiosity: why did you put it there in the first place? (maybe you had a good reason I'm not aware of)
As for this issue of rounding only the top, I think you'll need to create your own transformation and even than you'll have problems because even Android's Canvas API doesn't have built-in facilities to draw different corners. You can, however, do something like: copy full Bitmap to ARGB8888, then clear a 3dp by 3dp square to transparent, then over-draw a 6dp by 6dp circle of the source image so you get rounded corners there; OR extend RoundedBitmapDrawable and override the draw method like this (to draw over the bottom rounded corners with the original image's pixels):
@Override public void draw(Canvas canvas) {
super.draw(canvas);
Bitmap bitmap = getBitmap();
// corners of getBounds() with getCornerRadius() sides
RectF bottomLeft = ...;
RectF bottomRight = ...;
// calculate based on the output rects and getPaint().getShader().getLocalMatrix()
Rect bottomLeftBitmap, bottomRightBitmap = ...;
canvas.drawBitmap(bitmap, bottomLeftBitmap, bottomLeft, null);
canvas.drawBitmap(bitmap, bottomRightBitmap, bottomRight, null);
}
I just remembered that I have dealt with this drawable before, check out how you can use Glide's transcode facility to create it without a custom target:
.transcode(new RoundedDrawableTranscoder(context), RoundedBitmapDrawable.class)
.into(imageView)
Thank you for your prompt reply and, Thank you for your suggestions on how to make my app more efficient :+1:
Hi there again
After our last discussion, I changed my adapter base what you've said in this link and thanks, it's work more flexible. But some issue is there that annoying.
Base on your recommendation, I'm using @wasabeef, transformation library, but some starnge behavior occurred as I mention here
Now, more important thing to me is glide
this is what I'm using in my RecyclerView adapter:
glide.load(url)
.priority(Priority.IMMEDIATE)
.override(width, height)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.skipMemoryCache(true)
.priority(Priority.IMMEDIATE)
.bitmapTransform(new RoundedCornersTransformation(this.image.getContext(), AndroidUtilities.dpToPx(6, this.image.getContext()), 0, RoundedCornersTransformation.CornerType.TOP))
.listener(new RequestListener<String, GlideDrawable>() {
@Override public boolean onException(Exception error, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
@Override public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
return false;
}
})
.into(this.image);
Now my Questions:
skipMemoryCache(true), But When I remove this Heap Memory rising very fast! and this issue worry me in particular. Is it Okay?picasso. Is there any further configuration to get better result?``` java
public class GlideConfiguration implements GlideModule {
@Override public void applyOptions(Context context, GlideBuilder builder) {
// Prefer higher quality images unless we're on a low RAM device
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
builder.setDecodeFormat(ActivityManagerCompat.isLowRamDevice(activityManager) ? DecodeFormat.PREFER_RGB_565 : DecodeFormat.PREFER_ARGB_8888)
}
@Override public void registerComponents(Context context, Glide glide) {}
}
```
But When I remove this Heap Memory rising very fast!
Memory cache should help with scrolling a lot, the resources from memory can be loaded sync, whereas without it Glide has to go to the disk every time. I always think unused memory is a waste, it's better to cache something there for possible future use. As long as you can't reach an OOM it should be fine. Memory cache is bounded, so it won't raise to infinity, you can lower the size; this is the default (check what the calculator returns, maybe it's too big for your device):
int memoryCacheSize = new MemorySizeCalculator(context).getMemoryCacheSize();
builder.setMemoryCache(new LruResourceCache(memoryCacheSize));
I think my images load slower in compare with other libraries
You should measure that first, but make sure you're doing the same thing: there're a lot of things happening here and transformations are not cheap. You can always make loads faster by loading a smaller image (halve the w/h in override). Also make sure that the disk cache is hit (size and transformation has to match) and Glide doesn't go to the network on every display.
Are have any idea about strange behavior of
@wasabeeflibrary?
I commented there.
I changed My GlideConfiguration to this:
MemorySizeCalculator calculator = new MemorySizeCalculator(context);
int defaultMemoryCacheSize = calculator.getMemoryCacheSize();
int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
int customMemoryCacheSize = (int) (0.5 * defaultMemoryCacheSize);
int customBitmapPoolSize = (int) (0.5 * defaultBitmapPoolSize);
builder.setMemoryCache(new LruResourceCache(customMemoryCacheSize));
builder.setBitmapPool(new LruBitmapPool(customBitmapPoolSize));
Another thing that annoying is that when user scroll down and then back to top, loaded images in list does not here and seems that load again. I solved this issue by assign w/h to .override() and that works as charm But with new strategy ( based on your sample code), Despite of overriding, this happened, How can deal with this in this strategy?
Yep, size calculation looks good if that's what you want as the value, though I don't see why you just not / 2 instead of casting :)
Did you copy layoutParams.height = 0 in fixLayout? That's a really important line for caching.
If you have multiple qualities you can play around with thumbnail: load(low).thumbnail(load(thumb)) this will result in two downloads per list item, but the user should feel that it's faster than when using only low. You can apply the same transformation and crossFade so it just "clears up" when the better quality is loaded.
Yeap, I copy fixLayout As you used in sample code.
I confused about .thumbnail() , can you provid a snippet of code or a sample/tutorial link
I wrote it like this:
String lowImage = img.Url;
String thumbImage = timg.Url;
DrawableRequestBuilder<String > thumbnailRequest = glide.load(turl).dontAnimate();
glide.load(url)
.priority(Priority.IMMEDIATE)
.override(width, height)
.diskCacheStrategy(DiskCacheStrategy.RESULT)
.crossFade()
.thumbnail(thumbnailRequest)
.into(this.image);
ImageView when user back to top?If the thumbs are small enough the internet shouldn't be bad. I think if a user is concerned about internet usage they shouldn't be using an image-heavy app with limited internet then.
Try to use a lower priority than immediate, because Glide assigns thumbnails one class higher priority because it assumes they'll finish really fast; otherwise the thumbnail may be queued _after_ the normal load which defeats its purpose.
When you scroll back and forth for 2-3 rows only do the images load immediately? Does this time gap happen only when scrolling really far away from the top?
If it happens for 2-3 rows as well, try https://github.com/bumptech/glide/wiki/Debugging-and-Error-Handling to diagnose why the cache is not hit.
If it's happens only when you go far from top, then the memory cache is too small. Check the calculator's code to see what you're actually halving.
HIGH and it's get better than before, thanks for your advise :).crossFade() to glide request, image view get blink for a while!FragmanetStateViewPager and all of them contain a list like this, How can manage memory if I changed GlideConfiguration? I think the blink is https://github.com/bumptech/glide/issues/943#issuecomment-180839666, you can use that custom target to set it for now until that bug is fixed.
Yeah, lists in vewpager is an interesting question, I have yet to figure that out, you may get around it by unbinding the lists that are not visible (Glide.clear in onViewRecycled and probably setAdapter(null)) or decreasing the offscreen page size of the viewpager.
Hi there,
I'm here to say something about filling gap when user scroll list so far.
Based on sample you provided, I've used PauseOnFling() OnScrollListener. When I removed this, everything is Okay! and there is no delay to filling of images.
But I love that strategy,I think that is so goof for performance stuff :)
So you're saying that PauseOnFling causes a performance issue?
Oh No, I said that was so good to getting better performance!
Another issue raised here :(
When I using notifyItemChanged Image blinking!
this is my code:
String url = img.Url;
String turl = timg.Url;
DrawableRequestBuilder<String > thumbnailRequest = glide.load(turl).skipMemoryCache(true).crossFade(0);
int width = img.Width;
int height = img.Height;
fixlayout(width, height);
/* Is it GIF? set Gif badge*/
String URI = imgQ.ImageOriginal.Url;
String Extention = URI.substring(URI.lastIndexOf("."));
if((".gif").equals(Extention)){
image.setBadgeVisibility(true);
image.setBadge("GIF", initialGifBadgeColor);
}
glide.load(url)
.priority(Priority.HIGH)
.override(width, height)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.crossFade(500)
.thumbnail(thumbnailRequest)
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception error, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
progress.setVisibility(View.GONE);
/* Turning image from BW to Colorful animation*/
/*if(img.isIMAGE_HAS_FADED_IN()){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
ViewCompat.setHasTransientState(image, true);
final ObservableColorMatrix cm = new ObservableColorMatrix();
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
cm.setSaturation(animation.getAnimatedFraction());
if(image.getDrawable() != null){
image.getDrawable().setColorFilter(new ColorMatrixColorFilter(cm));
}
}
});
animation.setDuration(2000);
animation.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
ViewCompat.setHasTransientState(image, false);
};
});
animation.start();
img.setIMAGE_HAS_FADED_IN(true);
}
}*/
return false;
}
})
.into(new GlideDrawableImageViewTarget(this.image){
@Override
public void setDrawable(Drawable drawable) {
if(drawable instanceof TransitionDrawable || img.isIMAGE_HAS_FADED_IN()){
((TransitionDrawable) drawable).setCrossFadeEnabled(false);
}
super.setDrawable(drawable);
}
});
But still Image blinking :(
You're using skipMemoryCache on the thumbnail... so every time a new item is bound Glide has to go to the disk which takes time, and since you have no placeholder defined Glide will setImageDrawable(null) for that period.
Tips:
image.setColorFilter without any checks. No need to check for drawable.cm within the AnimatorUpdateListener anon inner class, just outside the update method.dontTransform() to make it explicit that it was intentional (if it was :).isIMAGE_HAS_FADED_IN in custom target may be unsafe as it is only checked if the drawable is NOT a TransitionDrawable, but you cast it anyway; did you want to use &&?Hi there,
I got OOM error in my app sometimes, specially on old devices
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:224)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor.afterExecute(FifoPriorityThreadPoolExecutor.java:96)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1096)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeStream(Downsampler.java:329)
at com.bumptech.glide.load.resource.bitmap.Downsampler.downsampleWithSize(Downsampler.java:220)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:153)
at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:50)
at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:19)
at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:39)
at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:20)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeBitmapWrapper(GifBitmapWrapperResourceDecoder.java:121)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeStream(GifBitmapWrapperResourceDecoder.java:94)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:71)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:61)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:22)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromSourceData(DecodeJob.java:190)
at com.bumptech.glide.load.engine.DecodeJob.decodeSource(DecodeJob.java:177)
at com.bumptech.glide.load.engine.DecodeJob.decodeFromSource(DecodeJob.java:128)
at com.bumptech.glide.load.engine.EngineRunnable.decodeFromSource(EngineRunnable.java:122)
at com.bumptech.glide.load.engine.EngineRunnable.decode(EngineRunnable.java:101)
at com.bumptech.glide.load.engine.EngineRunnable.run(EngineRunnable.java:58)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:444)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)聽
at java.lang.Thread.run(Thread.java:1019)聽
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)聽
I'm passed RequestManager to Adapter and use that as we talk before at this thread, but I got this error an app crashed :(
How can handle this? :(
It's simple: the bitmap doesn't fit. There are probably too many things in memory, or that single item is too big. You probably need to load a smaller image, but before you do that make sure that every non-visible Glide image target is cleared. RequestManager alone won't necessarily help, for example if you just stack fragments on top of each other the resources are still not freed (see #1337).
I've added Glide.with(this).onDestroy(); to onDestroyView() all fragments. But When first fragment load and recyclerview fills by data this happened [ Emulator - android API 10 ]:
D/dalvikvm: GC_CONCURRENT freed 1696K, 48% free 4783K/9031K, external 5681K/5952K, paused 0ms+0ms
D/dalvikvm: GC_EXTERNAL_ALLOC freed 351K, 44% free 5095K/9031K, external 5928K/5952K, paused 11ms
I/dalvikvm: Could not find method com.bumptech.glide.load.resource.drawable.GlideDrawable.getAlpha, referenced from method com.bumptech.glide.request.target.SquaringDrawable.getAlpha
W/dalvikvm: VFY: unable to resolve virtual method 23607: Lcom/bumptech/glide/load/resource/drawable/GlideDrawable;.getAlpha ()I
D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
D/dalvikvm: VFY: dead code 0x0005-0006 in Lcom/bumptech/glide/request/target/SquaringDrawable;.getAlpha ()I
I/dalvikvm: Could not find method com.bumptech.glide.load.resource.drawable.GlideDrawable.getCallback, referenced from method com.bumptech.glide.request.target.SquaringDrawable.getCallback
W/dalvikvm: VFY: unable to resolve virtual method 23608: Lcom/bumptech/glide/load/resource/drawable/GlideDrawable;.getCallback ()Landroid/graphics/drawable/Drawable$Callback;
D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
D/dalvikvm: VFY: dead code 0x0005-0006 in Lcom/bumptech/glide/request/target/SquaringDrawable;.getCallback ()Landroid/graphics/drawable/Drawable$Callback;
D/dalvikvm: GC_EXTERNAL_ALLOC freed 13K, 44% free 5096K/9031K, external 6660K/6852K, paused 10ms
D/dalvikvm: GC_EXTERNAL_ALLOC freed <1K, 44% free 5096K/9031K, external 6660K/6852K, paused 6ms
D/dalvikvm: GC_FOR_MALLOC freed <1K, 44% free 5096K/9031K, external 6730K/8404K, paused 5ms
D/dalvikvm: GC_EXTERNAL_ALLOC freed <1K, 44% free 5096K/9031K, external 6730K/8404K, paused 7ms
I/dalvikvm-heap: Clamp target GC heap from 16.515MB to 16.000MB
D/dalvikvm: GC_FOR_MALLOC freed 0K, 44% free 5096K/9031K, external 7279K/8404K, paused 5ms
D/dalvikvm: GC_EXTERNAL_ALLOC freed 2K, 44% free 5097K/9031K, external 7279K/8404K, paused 7ms
E/dalvikvm-heap: 500000-byte external allocation too large for this process.
D/dalvikvm: GC_FOR_MALLOC freed <1K, 44% free 5097K/9031K, external 6730K/8404K, paused 5ms
E/GraphicsJNI: VM won't let us allocate 500000 bytes
D/skia: --- decoder->decode returned false
D/dalvikvm: GC_EXTERNAL_ALLOC freed 1K, 44% free 5097K/9031K, external 6730K/8404K, paused 6ms
I/dalvikvm-heap: Clamp target GC heap from 16.516MB to 16.000MB
D/dalvikvm: GC_FOR_MALLOC freed 0K, 44% free 5097K/9031K, external 7279K/8404K, paused 5ms
E/PriorityExecutor: Request threw uncaught throwable
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:224)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor.afterExecute(FifoPriorityThreadPoolExecutor.java:96)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1096)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeStream(Downsampler.java:329)
at com.bumptech.glide.load.resource.bitmap.Downsampler.downsampleWithSize(Downsampler.java:220)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:153)
at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:50)
at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:19)
at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:39)
at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:20)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeBitmapWrapper(GifBitmapWrapperResourceDecoder.java:121)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeStream(GifBitmapWrapperResourceDecoder.java:94)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:71)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:61)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:22)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperStreamResourceDecoder.decode(GifBitmapWrapperStreamResourceDecoder.java:24)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperStreamResourceDecoder.decode(GifBitmapWrapperStreamResourceDecoder.java:14)
at com.bumptech.glide.load.resource.file.FileToStreamDecoder.decode(FileToStreamDecoder.java:39)
at com.bumptech.glide.load.resource.file.FileToStreamDecoder.decode(FileToStreamDecoder.java:17)
at com.bumptech.glide.load.engine.DecodeJob.loadFromCache(DecodeJob.java:222)
at com.bumptech.glide.load.engine.DecodeJob.decodeSourceFromCache(DecodeJob.java:109)
at com.bumptech.glide.load.engine.EngineRunnable.decodeFromCache(EngineRunnable.java:116)
at com.bumptech.glide.load.engine.EngineRunnable.decode(EngineRunnable.java:99)
at com.bumptech.glide.load.engine.EngineRunnable.run(EngineRunnable.java:58)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:444)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)聽
at java.lang.Thread.run(Thread.java:1019)聽
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)聽
D/dalvikvm: GC_EXTERNAL_ALLOC freed 77K, 44% free 5108K/9031K, external 7271K/8404K, paused 17ms
E/dalvikvm-heap: 622000-byte external allocation too large for this process.
I/dalvikvm-heap: Clamp target GC heap from 16.519MB to 16.000MB
D/dalvikvm: GC_FOR_MALLOC freed <1K, 44% free 5108K/9031K, external 7271K/8404K, paused 6ms
E/GraphicsJNI: VM won't let us allocate 622000 bytes
D/skia: --- decoder->decode returned false
E/PriorityExecutor: Request threw uncaught throwable
java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:224)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor.afterExecute(FifoPriorityThreadPoolExecutor.java:96)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1096)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1019)
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)
Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decodeStream(Downsampler.java:329)
at com.bumptech.glide.load.resource.bitmap.Downsampler.downsampleWithSize(Downsampler.java:220)
at com.bumptech.glide.load.resource.bitmap.Downsampler.decode(Downsampler.java:153)
at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:50)
at com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder.decode(StreamBitmapDecoder.java:19)
at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:39)
at com.bumptech.glide.load.resource.bitmap.ImageVideoBitmapDecoder.decode(ImageVideoBitmapDecoder.java:20)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeBitmapWrapper(GifBitmapWrapperResourceDecoder.java:121)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decodeStream(GifBitmapWrapperResourceDecoder.java:94)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:71)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:61)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperResourceDecoder.decode(GifBitmapWrapperResourceDecoder.java:22)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperStreamResourceDecoder.decode(GifBitmapWrapperStreamResourceDecoder.java:24)
at com.bumptech.glide.load.resource.gifbitmap.GifBitmapWrapperStreamResourceDecoder.decode(GifBitmapWrapperStreamResourceDecoder.java:14)
at com.bumptech.glide.load.resource.file.FileToStreamDecoder.decode(FileToStreamDecoder.java:39)
at com.bumptech.glide.load.resource.file.FileToStreamDecoder.decode(FileToStreamDecoder.java:17)
at com.bumptech.glide.load.engine.DecodeJob.loadFromCache(DecodeJob.java:222)
at com.bumptech.glide.load.engine.DecodeJob.decodeSourceFromCache(DecodeJob.java:109)
at com.bumptech.glide.load.engine.EngineRunnable.decodeFromCache(EngineRunnable.java:116)
at com.bumptech.glide.load.engine.EngineRunnable.decode(EngineRunnable.java:99)
at com.bumptech.glide.load.engine.EngineRunnable.run(EngineRunnable.java:58)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:444)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)聽
at java.lang.Thread.run(Thread.java:1019)聽
at com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor$DefaultThreadFactory$1.run(FifoPriorityThreadPoolExecutor.java:118)聽
D/dalvikvm: GC_EXTERNAL_ALLOC freed 77K, 44% free 5118K/9031K, external 7271K/8404K, paused 13ms
I/dalvikvm-heap: Clamp target GC heap from 16.533MB to 16.000MB
D/dalvikvm: GC_FOR_MALLOC freed <1K, 44% free 5118K/9031K, external 7275K/8404K, paused 5ms
D/dalvikvm: GC_EXTERNAL_ALLOC freed 1K, 44% free 5118K/9031K, external 7275K/8404K, paused 14ms
I/dalvikvm-heap: Clamp target GC heap from 16.538MB to 16.000MB
D/dalvikvm: GC_FOR_MALLOC freed <1K, 44% free 5118K/9031K, external 7279K/8404K, paused 5ms
D/FirebaseInstanceId: background sync failed: MISSING_INSTANCEID_SERVICE, retry in 20s
D/FirebaseInstanceId: background sync failed: MISSING_INSTANCEID_SERVICE, retry in 40s
So it's not a big image (500k). What I don't understand is the 44% free... if that much is available why OOM? You need take a heap dump and look for leaks. It's very likely it shouldn't be this full by default. Also make sure that your calculations for pool/cache don't exceed the available memory.
I'm not familiar with head dump image analyzing :cry:
Can you please guide me :sob:
Give me some references please, thank you
Hi there,
I need your help again man
I'm using your sample code for showing image loading progress.
But something happen here, When i'm scrolling and new item add to recyclerview, glide try to load all previous images in adapter! How can remove requests from queue of RequestManager?!
I've read your discussion under this issue topic and you said:
Glide.clear(View) only works if you passed an object extending ViewTarget to into(...)
and finally do it in recyclerview:
@Override public void onViewDetachedFromWindow(ViewHolder holder) {
Glide.clear(holder.contentsTarget);
holder.contentsTarget = null;
}
Now I've target in my viewholder, but I get NPE when assign null to target in viewholder at onViewDetachedFromWindow
How can remove those request from glide RequestManage?
You should start opening new issues, don't abuse this question as a personal support thread. ;)