Implementation and Optimization of Flutter Lightweight Engine for View‑Level Integration
This article details the background, design, memory and startup performance, business deployment, and a series of optimizations—including EngineGroup usage, entry‑point parameters, multi‑engine data communication, image‑cache sharing, iOSSurface release, and FlutterView size adaptation—of Flutter's lightweight engine for view‑level integration in mobile applications.
Background : Prior to Flutter 2.0, view‑level integration was limited, requiring either a single shared engine (FlutterViewController on iOS, FlutterActivity on Android) or a separate engine per page, each with trade‑offs in memory and maintenance. Flutter 2.0 introduced a lightweight engine that spawns new engines sharing threads and C++ resources, reducing memory overhead.
Solution Implementation :
EngineGroup : A new FlutterEngineGroup allows spawning lightweight engines that share resources. Developers create an EngineGroup and repeatedly call makeEngine to obtain new engines for pages.
Memory Usage : Official data shows each new engine adds only ~180 KB. Real‑world Android tests show a 3.8‑4.8 MB increase per Flutter card, while iOS shows larger increments due to iOSurface allocation.
Startup Speed : Measured speed improvements are ~2.63× on Android and ~9× on iOS when using the lightweight engine.
Business Deployment : The lightweight engine was applied in several ByteDance products (e.g., 大力家长, 小荷, 幸福里). Use cases include converting photo‑prompt dialogs and tab switching to lightweight engines, achieving reduced first‑frame latency (from 96 ms to 78 ms) and smoother page transitions.
Feature Optimizations :
Entry‑Point Parameters : Added @pragma('vm:entry-point') functions with arguments to pass data from native to Flutter. Example:
void main() {
runApp(HomePage());
}
@pragma('vm:entry-point')
void home() {
runApp(HomePage());
}
@pragma('vm:entry-point')
void home(List
args) {
runApp(HomePage(extras: args));
}Multi‑Engine Data Communication : Since isolates in the same IsolateGroup do not share memory, a service isolate is introduced to broadcast updates. Code example for a broadcast channel:
BroadcastChannel channel = BroadcastChannel('countService');
channel.onDataUpdated = (dynamic content) {
setState(() {
int counter = content as int;
_counter = counter;
});
print('this will be invoked after data has been changed');
};
BroadcastChannel channel = BroadcastChannel('countService');
channel.onReceiveNoti = (dynamic content) {
print('this will be invoked after receive notification');
};ImageCache Sharing : To avoid duplicated image decoding across engines, a C++ map caches CanvasImage and Codec objects. Subsequent engines create proxy objects that forward calls to the shared resources, dramatically reducing memory consumption.
iOSSurface Release : Implemented logic to release ios_surface when a FlutterViewController becomes invisible, cutting per‑page memory growth from ~5 MB to ~500 KB.
FlutterView Size Adaptation : Wrapped content in a custom RootWrapContentWidget that measures layout size and reports it to native, enabling dynamic sizing of Flutter views inside list items or banners. Example widget:
class RootWrapContentWidget extends StatelessWidget {
const RootWrapContentWidget({Key? key, required this.child, this.wrapWidth = false, this.wrapHeight = false})
: assert(child != null),
assert(wrapWidth || wrapHeight),
super(key: key);
final Widget child;
final bool wrapWidth;
final bool wrapHeight;
@override
Widget build(BuildContext context) {
Widget result = _RootSizeChangeListener(child: child);
if (wrapWidth) result = IntrinsicWidth(child: result);
if (wrapHeight) result = IntrinsicHeight(child: result);
return result;
}
}Conclusion and Outlook : The lightweight engine significantly improves memory and startup performance for view‑level Flutter integration. Ongoing work includes better plugin registration, engine destruction strategies, global configuration, and further cache optimizations. ByteDance will continue contributing improvements back to the Flutter community.
ByteDance Terminal Technology
Official account of ByteDance Terminal Technology, sharing technical insights and team updates.
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.