Search code examples
androidviewbitmapandroid-custom-view

Where to properly deallocate bitmap on Android View?


I have a custom View, that draws a bunch of stuff including bitmaps. I want to cache this drawing onto a bitmap, so that I just need to draw one single bitmap inside onDraw, rather than repeating these drawing tasks and calculation.

Bitmaps need to be recycled after we are no longer using it. I don't see onDestroy() or anything remotely similar in the View class. Is there a callback method I can override to achieve this?

public void <insert_callback_here>() {
    cachedBitmap.recycle();
}

There is no animation. This is a static image. There are plenty of calculations done to draw the image, so I'd rather do it once on onMeasure().


Solution

  • I'm going to answer my own here. The proper methods to override is onDetachedFromWindow. I deallocate my bitmap inside onDetachedFromWindow, and reallocate them inside onMeasure if the width or height have changed.

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (cachedBitmap != null && !cachedBitmap.isRecycled()) {
            cachedBitmap.recycle();
            cachedBitmap = null;
            cachedBitmapWidth = -1;
            cachedBitmapHeight = -1;
        }
    }
    
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int viewWidth = MeasureSpec.getSize(widthMeasureSpec);;
        int viewHeight = MeasureSpec.getSize(heightMeasureSpec);;
    
        if (cachedBitmapWidth != viewWidth || cachedBitmapHeight != viewHeight) {
            if (cachedBitmap != null) {
                cachedBitmap.recycle();
            }
            cachedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            cachedBitmapWidth = viewWidth;
            cachedBitmapHeight = viewHeight;
            Canvas canvas = new Canvas(cachedBitmap);
            // do drawings here..
        }
    
        setMeasuredDimension(viewWidth, viewHeight);
    }