What is Canvas api in Android ?
In Jetpack Compose, the Canvas API is a declarative, stateless way to draw custom shapes, paths, and images. Unlike the traditional View system where you override onDraw(canvas), Compose uses a Canvas composable that provides a DrawScope.
Canvas(modifier = Modifier.size(200.dp)) {
// The DrawScope starts here
drawCircle(
color = Color.Blue,
radius = size.minDimension / 4,
center = center // 'center' and 'size' are provided by DrawScope
)
}
Lifecycle
The Canvas follows the standard Compose "Three Phases" of a frame, but it spends most of its time in the final phase.
Composition (What to show)
Compose determines that aCanvasshould be part of the UI tree. If you usemutableStateOfinside youronDrawblock, Compose tracks this as a dependency.Layout (Where to show it)
TheModifier.size()or constraints from the parent determine the Canvas's height and width. This is where thesizeproperty of theDrawScopeis calculated.Drawing (How to show it)
This is where the internal "Magic" happens. Unlike Composition, which can be expensive, the Draw Phase is optimized for high frequency (60fps or 120fps).Invalidation: When a state variable used inside onDraw changes, Compose doesn't necessarily re-run the "Composition" phase. It simply invalidates the layer and re-runs the drawing commands.
Recording: Modern Android uses a Hardware Accelerated
canvas. YourdrawCirclecommands are actually recorded into a DisplayList. The GPU then "plays back" these commands to render pixels on the screen.
How XML-Based Canvas Works Internally
In the legacy system, you create a custom View and override the onDraw(canvas: Canvas) method.
The Invalidation Loop:
When you want to update the UI, you callinvalidate(). This tells the Choreographer that the view is "dirty". On the next VSYNC signal, the system callsdraw()on the view hierarchy.The Native Canvas:
The canvas object passed toonDrawis a direct wrapper around the Skia drawing engine (written in C++).The Paint Object: Unlike Compose, where you pass parameters like color directly into the
drawfunction, XML Views require aPaintobject. This object holds the configuration (aliasing, color, stroke width) and must be managed manually.
Comparing the Lifecycles
| Feature | XML Canvas (View) | Compose Canvas |
|---|---|---|
| Trigger | Manual invalidate() call. | Automatic via State observation. |
| Object Lifetime | Manual (usually in init). | drawWithCache or manual management. |
| Coordinate System | Pixels (requires DisplayMetrics). | Pixels (DrawScope provides Density). |
| Hardware Accel. | Controlled via LayerType. | Enabled by default; uses GraphicsLayer. |
How to Optimize Both
Optimization strategies differ because of how the two systems handle memory and updates.
Optimizing XML Canvas
Avoid Allocations in
onDraw: Never usenew Paint()ornew Path()insideonDraw. These trigger the Garbage Collector, causing "Jank" (dropped frames). Initialize them in the constructor.Use
Canvas.clipRect(): If only a small part of your view changes, useinvalidate(Rect)to only redraw that specific area, saving GPU cycles.Hardware Layers: For complex animations, use
setLayerType(LAYER_TYPE_HARDWARE, paint). This caches the view as a bitmap on the GPU so it doesn't have to re-execute drawing commands every frame.
Optimizing Compose Canvas
Modifier.drawWithCache: Use this to initialize paths or shaders. It only re-calculates when the size of the canvas changes or a state inside the cache block changes.Static Parameters: Don't pass raw
Stateobjects into the Canvas if they change frequently unless necessary. Use lambda-based modifiers to prevent the entire composable from recomposing.Use
GraphicsLayer: ApplyModifier.graphicsLayer { ... }to offload transformations (rotation, scale, alpha) to the GPU. This avoids re-running theonDrawlogic entirely.
Internal Rendering Architecture
Both ultimately end up at the Hardware Renderer.
- DisplayList: Both systems record your commands (drawRect, drawLine) into a
DisplayList. - RenderThread: This list is sent to a dedicated
RenderThreadthat talks to the GPU. - Skia/Vulkan: The GPU uses the Skia engine (or the newer Impeller / Vulkan backends) to turn those commands into actual colored pixels.
Comments
Post a Comment