Flutter 3.44's HCPP Eliminates the Performance Tax on Android Platform Views
Welcome to follow the WeChat official account: FSA Full Stack Action 👋
I. Background: The Evolution of Android Platform Views
If you have ever embedded Google Map, WebView, or a native video player in a Flutter project, you have certainly experienced the "dilemma" brought by Platform View.
For a long time, integrating native views in Flutter has been like walking a tightrope: either choose Virtual Display, which causes native keyboard and accessibility features to stop working entirely; or choose Hybrid Composition, which turns a smooth 120Hz scroll into a "slideshow" with frame rates plummeting.
To solve this problem, the Flutter team has been working on it for a long time. Let's first review the currently known solutions and their pros and cons. After reading this, you will understand why HCPP is so important.
1. Solution Comparison
Solution |
Rendering Performance |
Interaction Experience |
Core Pain Point |
|
Extremely High |
Extremely Poor |
Cannot handle keyboard focus, cannot support accessibility services |
|
Extremely Low |
Perfect |
High thread synchronization overhead, frequent frame drops during scrolling |
|
Medium |
Medium |
Minor stuttering or clipping issues still occur during high-speed scrolling |
|
Extremely High |
Perfect |
Requires |
2. Core Differences
Virtual Display: TheFlutterengine draws an "invisible canvas" (GPU Texture) in the background, lets the native view draw on it, and then pastes this canvas onto the screen. This solution renders extremely fast, but the system is completely unaware of the native view's existence, so interactions like keyboard input and text selection are all broken.Hybrid Composition: To solve the interaction problem,Flutterdirectly inserts the native view intoAndroid's view hierarchy. Although the experience is good, the cost is thatFlutter's rendering thread andAndroid's main thread must frequently "meet" to synchronize and constantly copy pixel data between the two threads, resulting in a terrifying performance loss (Rendering Tax).TLHC: This was a previous compromise solution, usingSurfaceTexturefor optimization. Although faster thanHC, it still cannot escape frame drops and visual tearing during fast scrolling.
II. HCPP Principles: Breaking the "Rendering Tax"
The goal of Hybrid Composition++ (abbreviated as HCPP), introduced in Flutter 3.44, is to achieve: Both the high performance of Virtual Display and the perfect interaction of Hybrid Composition.
Its core idea is: Since the "pixel merging" step is the most expensive, let's simply not merge them and let the system (OS) handle it directly.
1. Understanding Surface
To understand HCPP, you must first grasp the Surface in the Android graphics system.
You can think of the physical screen as a projection stage:
The
Flutterengine draws the UI on film A, generating aSurface.The native view (like
Google Map) draws its content on film B, also generating aSurface.
Previously, Flutter had to piece together A and B at home before handing them over. HCPP's approach is: stack A and B together and throw them directly to the system's dispatcher (SurfaceFlinger), letting it complete the composition at the hardware level.
2. HCPP's Pipeline Logic
The workflow of HCPP is as follows:
ImpellerRendering:Flutteruses the newImpellerengine (based onVulkan) to render the UI, generating a nativeSurface.Native View Rendering: The native component (like
WebView) draws on its ownSurface.SurfaceControlSubmission:Flutterno longer attempts to merge pixels but encapsulates these twoSurfaces into aSurfaceControltransaction.SurfaceFlingerComposition:Android's systemSurfaceFlingerreceives the instruction and directly stacks the two layers together at the hardware level.
Because there is no need to repeatedly copy GPU texture data between the Flutter thread and the Android thread, the frame drops (Jank) caused by thread synchronization are completely eliminated.
III. Practice: How to Enable HCPP in Your Project
Currently, HCPP is still an "optional configuration" feature. To experience it, your device must meet the following requirements: Android 14 (API 34) or higher, support for Vulkan, and the Impeller engine enabled.
1. Configure AndroidManifest.xml
First, you need to manually enable this switch under the application node in android/app/src/main/AndroidManifest.xml:
<application ...>
<meta-data
android:name="io.flutter.embedding.android.EnableHcpp"
android:value="true" />
<activity ...>
...
</activity>
</application>
2. Dart Layer Integration
On the Dart side, you need to use PlatformViewLink with AndroidViewSurface to implement it:
class AndroidNativeTextHcpp extends StatelessWidget {
final String text;
const AndroidNativeTextHcpp({super.key, required this.text});
@override
Widget build(BuildContext context) {
const String viewType = 'custom-native-text';
final Map<String, dynamic> creationParams = <String, dynamic>{'text': text};
return PlatformViewLink(
viewType: viewType,
surfaceFactory: (context, controller) {
return AndroidViewSurface(
controller: controller as AndroidViewController,
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
onCreatePlatformView: (params) {
return PlatformViewsService.initHybridAndroidView(
id: params.id,
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
onFocus: () => params.onFocusChanged(true),
)
..addOnPlatformViewCreatedListener(params.onPlatformViewCreated)
..create();
},
);
}
}
3. Native Side Implementation (Kotlin)
You also need to register your native view factory in MainActivity.kt:
class MainActivity : FlutterActivity(){
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
flutterEngine
.platformViewsController
.registry
.registerViewFactory("custom-native-text", NativeTextViewFactory())
}
}
4. Run Tests
Since this feature has hardware requirements, it is recommended to connect a real device for testing and use profile mode to check performance. Note that you must add the --enable-hcpp parameter:
flutter run --profile --enable-hcpp
IV. Conclusion
A very clever aspect of HCPP's design is its fallback mechanism. If a user is on an older device (like Android 12) or does not support Vulkan, the Flutter engine will automatically fall back to TLHC mode. As a developer, you only need to write one set of code, and the rest of the performance optimization is handled automatically by Flutter.
The emergence of HCPP marks another step up in the maturity of Flutter on the Android platform. If you are dealing with complex map, video, or document viewing features, it's time to pay attention to this new feature.
If you find this content helpful, feel free to give it a like and follow me for more Flutter practical tips.
References
Flutter Official Documentation: Hosting native Android views
Android Developer Guide: Surface API Documentation
If the article has been helpful to you, please click to follow my WeChat official account: FSA Full Stack Action, which will be the greatest encouragement for me. The official account not only has Android technology, but also articles on iOS, Python, etc. There may be skill points you want to learn about~