In Flutter on Android, how do texture layer, hybrid composition and HCPP platform views differ, and what does each cost in frame rate?
answer
- texture copy vs view hierarchy
- SurfaceView forces a fallback
- hybrid composition merges raster into platform thread
- HCPP: API 34, Vulkan, Impeller
- initSurfaceAndroidView vs initExpensiveAndroidView
basics
~20 sTexture layer renders the native view into a texture Flutter composites, keeping Flutter fast but janking on fast scrolls. Hybrid composition puts it in the Android view hierarchy with full fidelity but merges raster work onto the platform thread. HCPP is an experimental, faster hybrid mode.
solid answer
~40 s**Texture layer hybrid composition (TLHC)** — the default for `AndroidView` — renders the native view into a texture that Flutter composites: Flutter performance stays good and transforms work, but fast-scrolling content such as a web view can jank, and `SurfaceView` content breaks it, so the view falls back. **Hybrid composition (HC)** — `PlatformViewLink` with `AndroidViewSurface` and `initExpensiveAndroidView` — leaves the view in the Android hierarchy and draws Flutter into `FlutterImageView` layers around it: full fidelity, accessibility and `SurfaceView` support, but Flutter merges its raster thread into the platform thread, which lowers FPS. **HCPP** (experimental since Flutter 3.44) needs Android API 34+, Vulkan and Impeller, composites both surfaces in the system compositor with synchronised transactions, and is enabled by `--enable-hcpp` or a manifest `meta-data` flag, falling back automatically on unsupported devices.
code
xml · 5 lines<application>
<meta-data
android:name="io.flutter.embedding.android.EnableHcpp"
android:value="true" />
</application>go deeper
Remember that Android offers several platform view modes and that the default renders the native view into a texture.
Map each API to its mode and fallback: AndroidView to TLHC or virtual display, initSurfaceAndroidView to TLHC or HC, initExpensiveAndroidView to HC.
Choose a mode from measured frame times and native requirements such as SurfaceView and accessibility, and explain the thread-merge cost of hybrid composition.
Set a policy for experimental HCPP adoption against your device mix, including rollout, fallback behaviour and how you would detect regressions.
## Why Android has several modes On Android, a native `View` and Flutter's output must end up in one image on screen. There is more than one way to do that, and each trades Flutter frame rate against native fidelity. The framework exposes the choice through which widget and which `PlatformViewsService` call you use. ## The modes | Mode | How it composes | Strengths | Costs | |---|---|---|---| | **Texture layer (TLHC)** | Native view renders to a texture; Flutter's renderer draws that texture with everything else | Good Flutter performance; all transforms work | Jank on quick scrolling (e.g. web views); `SurfaceView`s lose accessibility; text magnifier breaks | | **Hybrid composition (HC)** | Native view stays in the Android view hierarchy; Flutter draws into `ImageReader`-backed `FlutterImageView`s (a background layer plus overlays for content above the view) | Full native fidelity; correct accessibility; `SurfaceView` works | Raster thread merged into the platform thread → lower Flutter FPS; before Android 10, extra per-frame memory copies | | **HCPP** (experimental, 3.44+) | Native view and Impeller each render to a native surface; the system compositor combines them with synchronised transactions | Fidelity of HC without its sync overhead | Needs API 34+, Vulkan and Impeller; experimental; known issue with transparent views in complex overlay stacks | | **Virtual display** (fallback) | Native view drawn into an off-screen virtual display, then into a texture | Works where TLHC cannot | Extra graphic buffers; jank on high-frequency updates | ## Which API picks which mode 1. `AndroidView` → `PlatformViewsService.initAndroidView`: TLHC when possible, **virtual display** when not. 2. `PlatformViewLink` + `AndroidViewSurface` with `initSurfaceAndroidView`: TLHC when possible, **hybrid composition** when not. 3. `initExpensiveAndroidView`: always hybrid composition. 4. `initHybridAndroidView`: always HCPP, for devices that support it. TLHC is "not possible" when the embedded view contains a `SurfaceView`, because such views draw out-of-band where the texture path cannot see the updates. ## Turning on HCPP HCPP is a global upgrade enabled by configuration, not by a Dart call: - `flutter run --enable-hcpp` or `flutter test --enable-hcpp` for local runs — the flag cannot be passed to `flutter build`; - for releases, a `<meta-data android:name="io.flutter.embedding.android.EnableHcpp" android:value="true" />` entry in the `<application>` block of `AndroidManifest.xml`. On devices without API 34+, usable Vulkan or Impeller, Flutter falls back to the app's configured strategy. ## Choosing, with a map inside a scrolling page as the example - Start with the default (TLHC). Measure scrolling with the map on screen on a mid-range device. - If the native view uses a `SurfaceView` (some map and video SDKs do) or accessibility inside the view matters, move to hybrid composition and accept the FPS cost; keep the view small and avoid heavy Flutter effects over it. - Consider HCPP on a test build if your users skew to recent devices, and keep a fallback in mind. - Plugins often expose the choice: `webview_flutter_android` has `displayWithHybridComposition`, and `google_maps_flutter_android` has `useAndroidViewSurface`. ## Pitfalls - Assuming one mode is "best": each is a trade-off, and the framework docs present them as such. - Forgetting that `SurfaceView` content silently changes which mode you get. - Blaming Flutter code for jank that comes from hybrid composition's thread merge; frame-timing diagnosis itself is its own topic.
- Your AndroidView hosts a video SDK built on SurfaceView. What mode do you actually get?Not texture layer: the engine detects the `SurfaceView` and falls back. With plain `AndroidView` it falls back to virtual display; with `PlatformViewLink` and `initSurfaceAndroidView` it falls back to hybrid composition. Choose the latter deliberately if you need correct accessibility.
- Why does hybrid composition lower Flutter's frame rate?To keep native views and the Flutter canvas in sync, Flutter merges its raster thread into the platform thread. Rasterising complex widgets then competes with OS messages and plugin work on that thread, so frames drop.
- Can you enable HCPP for a release with flutter build --enable-hcpp?No. The flag exists only for `flutter run` and `flutter test`. Release builds opt in through the `io.flutter.embedding.android.EnableHcpp` meta-data entry in `AndroidManifest.xml`.
saying these in an interview costs you the question
- Hybrid composition is always the fastest mode for Flutter's own frames.
- Texture layer mode supports SurfaceView content without any fallback.
- HCPP is the stable default on every Android device in 3.47.
- The --enable-hcpp flag works with flutter build for release APKs.
- All Android platform view modes have identical accessibility behaviour.