16

Please explain how does the drawing cache work in Android. I'm implementing a custom View subclass. I want my drawing to be cached by the system. In the View constructor, I call

setDrawingCacheEnabled(true);

Then in the draw(Canvas c), I do:

    Bitmap cac = getDrawingCache();
    if(cac != null)
    {
        c.drawBitmap(cac, 0, 0, new Paint());
        return;
    }

Yet the getDrawingCache() returns null to me. My draw() is not called neither from setDrawingCacheEnabled(), nor from getDrawingCache(). Please, what am I doing wrong?

Ragunath Jawahar
  • 19,513
  • 22
  • 110
  • 155
Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • Possible duplicate of http://stackoverflow.com/questions/2817166/android-2-1-views-getdrawingcache-method-always-returns-null – Hasturkun Jun 15 '10 at 15:55
  • 2
    Different - that one concerns requesting a cache for a system-provided child view, this one is about building it in your own view. – Seva Alekseyev Jun 15 '10 at 15:59
  • This will work - http://stackoverflow.com/questions/11560882/call-to-getdrawingcache-fails-on-api-8-everytime – Ron Jul 19 '12 at 18:45

2 Answers2

9

There's a hard limit on drawing cache size, available via the ViewConfiguration class.. My view is larger than allowed for caching.

FYI, the sources of the View class are available via the SDK Manager for some (not all) Android versions.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
6

Hopefully this explains it.

public class YourCustomView extends View {

    private String mSomeProperty;

    public YourCustomView(Context context) {
        super(context);
    }

    public YourCustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public YourCustomView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setSomeProperty(String value) {
        mSomeProperty = value;
        setDrawingCacheEnabled(false); // clear the cache here
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // specific draw logic here

        setDrawingCacheEnabled(true); // cache
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        ...
    }

}

Example code explained.

  1. In the setSomeProperty() method call setDrawingCacheEnabled(false) to clear the cache and force a redraw by calling invalidate().
  2. Call setDrawingCacheEnabled(true) in the onDraw method after drawing to the canvas.
  3. Optionally place a log statement in the onDraw method to confirm it is only called once each time you call the setSomeProperty() method. Be sure to remove the log call once confirmed as this will become a performance issue.
  • 3
    Does this actually work, cause documentation seems to explain it differently: Enables or disables the drawing cache. When the drawing cache is enabled, **the next call to getDrawingCache() or buildDrawingCache() will draw the view in a bitmap** Whether I add those lines or not my onDraw() only gets called once each time I call invalidate() Tested: cache is not used. – 3c71 Oct 13 '12 at 09:23
  • 2
    This is wrong. You only need to enable the drawing cache and it will be populate on each call to draw. This actually won't work because the drawing cache will not be enabled on the first call to onDraw. – dcow Aug 09 '13 at 21:02