Evolution of FlutterEngine on Beike PAD: From Single Engine to EngineGroup
This article details Beike PAD's journey with FlutterEngine, covering its initial single‑engine setup, the challenges of multi‑engine flashing, the custom communication plugin for engine isolation, and the adoption of FlutterEngineGroup in Flutter 2.0 to reduce memory usage and improve performance.
Beike has been developing multiple products for iPad and Android tablets (collectively referred to as PAD) using Flutter to achieve a unified UI across platforms.
On smartphones, a full‑screen Flutter page can be loaded with a single FlutterActivity . However, PAD screens are larger and involve richer interactions, including maps and embedded H5 pages, leading to mixed Native and Flutter content that requires FlutterFragment and fragment switching. Consequently, a hybrid Native + Flutter solution with FlutterEngine as the bridge became essential.
Beike PAD experienced three major stages of FlutterEngine usage: a single engine, multiple engines, and finally the FlutterEngineGroup introduced in Flutter 2.0.
FlutterEngine Overview
A FlutterEngine is a single Flutter execution environment. It allows Dart code to run inside an Android application and can render UI via FlutterRenderer . Multiple engines can coexist, each isolated via Isolate ports, and share a single Dart VM after the first engine loads the native libraries.
Key components of a FlutterEngine include:
FlutterLoader : loads Flutter resources and native libraries.
FlutterJNI : defines the Java‑C/C++ interop functions.
DartExecutor : creates a DartExecutor.DartEntrypoint and runs Dart code via executeDartEntrypoint(DartExecutor.DartEntrypoint) (this method must not be called twice).
Other components: system channel initialization and automatic plugin registration.
1. Single FlutterEngine
Initially, Beike PAD cached a single FlutterEngine at startup and bound all pages to it. This worked for full‑screen Flutter pages but caused flashing when multiple tabs mixed Native fragments with Flutter fragments, because the same engine was bound to different FlutterView instances during tab switches.
2. Multi‑Engine Reuse Strategy
To avoid flashing, several pre‑loaded engines were cached, and each tab selected a distinct engine. This isolated business logic but introduced higher memory consumption (≈20 MB per engine before Flutter 2.0) and communication challenges between engines.
Beike built a custom communication plugin that registers an EventMethodChannel for each engine during onAttachedToEngine . The plugin caches these channels, allowing Native code to broadcast messages to all engines or specific ones, solving the data‑sync issue.
3. FlutterEngineGroup in Flutter 2.0
Flutter 2.0 introduced FlutterEngineGroup , which creates lightweight engines (≈180 KB each) that share GPU context, font metrics, and isolate group snapshots. Beike now creates a persistent engine via the group at app start and spawns additional engines on demand, dramatically reducing memory overhead.
Comparisons show the EngineGroup approach consumes far less memory than the previous multi‑engine solution while retaining isolation and fast startup.
Conclusion
Beike PAD has successfully migrated to Flutter 2.0 with EngineGroup, and future work will explore deeper memory‑saving techniques and performance optimizations for Flutter on large‑screen tablets.
Beike Product & Technology
As Beike's official product and technology account, we are committed to building a platform for sharing Beike's product and technology insights, targeting internet/O2O developers and product professionals. We share high-quality original articles, tech salon events, and recruitment information weekly. Welcome to follow us.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.