Android-BitmapCache
Android-BitmapCache copied to clipboard
TransitionDrawable and Recycled Bitmap Exception
I've got a recycled bitmap issue cropping up when using a TransitionDrawable. I'm seeing this pretty consistently on an HTC Desire HD running 2.3.3, and sporadically on other devices. I'm using version 2.3 and the cache is configured for memory only.
I am able to get work around the issue by manually calling cbd.setBeingUsed(true); after pulling the bitmap from the cache, like so (and yes, mImageView is an instance of CacheableImageView):
private void animate() {
if (mImageView == null) { Log.w(TAG,"Null imageview?"); return; }
if (this.isDetached()) { Log.w(TAG,"Attempting animation on detached fragment."); return; }
int imageIndex = getNextIndex();
currentIndex = imageIndex;
String index = String.valueOf(images[imageIndex]);
CacheableBitmapDrawable cbd = null;
if (mCache.contains(index)) {
cbd = mCache.get(index);
}
if (cbd == null || !cbd.isBitmapValid()) {
cbd = mCache.put(index, BitmapFactory.decodeResource(getResources(), images[imageIndex]));
}
// without this, I get sporadic recycled bitmap errors!
cbd.setBeingUsed(true);
Drawable[] drawables = new Drawable[2];
drawables[0] = mImageView.getDrawable();
drawables[1] = cbd;
TransitionDrawable transitionDrawable = new TransitionDrawable(drawables);
transitionDrawable.setCrossFadeEnabled(true);
mImageView.setImageDrawable(transitionDrawable);
transitionDrawable.startTransition(2000);
}
The stack trace is:
java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@40644e28 at
android.graphics.Canvas.throwIfRecycled(Canvas.java:973) at
android.graphics.Canvas.drawBitmap(Canvas.java:1062) at
android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:325) at
uk.co.senab.bitmapcache.CacheableBitmapDrawable.draw(CacheableBitmapDrawable.java:77) at
android.graphics.drawable.TransitionDrawable.draw(TransitionDrawable.java:204) at
android.graphics.drawable.TransitionDrawable.draw(TransitionDrawable.java:196) at
android.graphics.drawable.TransitionDrawable.draw(TransitionDrawable.java:196) at
android.widget.ImageView.onDraw(ImageView.java:935) at
android.view.View.draw(View.java:6971) at
android.view.ViewGroup.drawChild(ViewGroup.java:1710) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.View.draw(View.java:6974) at
android.view.ViewGroup.drawChild(ViewGroup.java:1710) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.View.draw(View.java:6974) at
android.support.v4.view.ViewPager.draw(ViewPager.java:2157) at
android.view.ViewGroup.drawChild(ViewGroup.java:1710) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.View.draw(View.java:6974) at
android.widget.FrameLayout.draw(FrameLayout.java:357) at
android.view.ViewGroup.drawChild(ViewGroup.java:1710) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.View.draw(View.java:6974) at
android.widget.FrameLayout.draw(FrameLayout.java:357) at
com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1929) at
android.view.ViewRoot.draw(ViewRoot.java:1590) at
android.view.ViewRoot.performTraversals(ViewRoot.java:1290) at
android.view.ViewRoot.handleMessage(ViewRoot.java:1939) at
android.os.Handler.dispatchMessage(Handler.java:99) at
android.os.Looper.loop(Looper.java:143) at
android.app.ActivityThread.main(ActivityThread.java:4196) at
java.lang.reflect.Method.invokeNative(Native Method) at
java.lang.reflect.Method.invoke(Method.java:507) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) at
dalvik.system.NativeStart.main(Native Method)
Ugh. So with cbd.setBeingUsed(true), it looks like on some devices, I wind up with out of memory errors. :(
You can try using FileDescriptor to decode from DiskCache. keep decodeStream when putting CacheableBitmapDrawable to MemoryCache.
I loaded 300 high quality images in grid view. sorry my english is bad.