views:

124

answers:

2

In the Android MapsDemo available in Eclipse for the Google API, they create an inner class SmoothCanvas in MapViewCompassDemo.java. Within this class the re-implement seemingly every method and reroute it to a delegate instance of Canvas.

static final class SmoothCanvas extends Canvas {
    Canvas delegate;

    private final Paint mSmooth = new Paint(Paint.FILTER_BITMAP_FLAG);

    public void setBitmap(Bitmap bitmap) {
        delegate.setBitmap(bitmap);
    }

    public void setViewport(int width, int height) {
        delegate.setViewport(width, height);
    }
    ...

What is the point of the delegate in this instance?

A: 

The key point of delegating in that instance is:

private final Paint mSmooth = new Paint(Paint.FILTER_BITMAP_FLAG);

FILTER_BITMAP_FLAG bit. Filtering affects the sampling of bitmaps when they are transformed. Filtering does not affect how the colors in the bitmap are converted into device pixels. That is dependent on dithering and xfermodes.

By activating that flag, drawing bitmaps will basically increase its performance. You will in the example that mSmoth is used in every drawBitmap call.

Cristian
How does that create the need to use a delegate though? I think you are answering why they created the `SmoothCanvas` class that extends `Canvas`. That I understand. What I don't understand is why they created the property `delegate` of type `Canvas` when they were already in a `Canvas` class?
Josh Russo
A: 

The value of delegate is passed in to dispatchDraw. The SmoothCanvas class is a wrapper around delegate. By delegating, the Canvas implementation passed to dispatchDraw does all the heavy lifting. The wrapper just allows the injection of the smoothed paint without implementing all the logic of Canvas.

Devon_C_Miller
Why did they not just override the few methods that use the Paint object? Like so: (there's more but there is not room to paste it all) static final class SmoothCanvas extends Canvas { private final Paint mSmooth = new Paint(Paint.FILTER_BITMAP_FLAG); @override public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { if (paint == null) { paint = mSmooth; } else { paint.setFilterBitmap(true); } super.drawBitmap(bitmap, left, top, paint); }
Josh Russo
didn't realize the indent doesn't work in comments:http://paste-it.net/public/e4a86ba/java/
Josh Russo
Delegation handles the case where the argument to dispatchDraw is not Canvas, but a derivative. Consider what happens if the Canvas passed in is already overridden to do something else: blur the bitmap, render in greyscale, etc. If you just supply you own overridden Canvas, you may loose functionality. By delegating, you use the original object, but with a few changes.
Devon_C_Miller
Gotcha, thanks.
Josh Russo