TransitionDrawable and Recycled Bitmap Exception #36

Open
mandrachek opened this Issue Aug 23, 2013 · 2 comments

Projects

None yet

2 participants

@mandrachek

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)
@mandrachek

Ugh. So with cbd.setBeingUsed(true), it looks like on some devices, I wind up with out of memory errors. :(

@shawnthye

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment