Mobile Development 15 min read

Embedding Flutter Views in React Native and Native Applications: Architecture, Implementation, and Lessons Learned

This article explores the practical integration of Flutter views within React Native and native mobile pages, detailing architectural choices, lifecycle management, event handling, and code implementations to enable seamless cross‑stack UI composition in a large‑scale travel app.

Ctrip Technology
Ctrip Technology
Ctrip Technology
Embedding Flutter Views in React Native and Native Applications: Architecture, Implementation, and Lessons Learned

The rapid evolution of multi‑platform technologies has blurred the boundaries between mobile and front‑end development, prompting Ctrip's hotel team to investigate embedding Flutter views inside both React Native (RN) and native containers.

Background : Hotel list and detail pages have migrated to Flutter, but new business scenarios require reusing the same Flutter UI across RN and native screens, demanding a flexible embedding solution.

RN Integration : Directly overlaying a Flutter view on the RN layer proved problematic due to offset calculations, lifecycle synchronization, and event propagation. Instead, the team wrapped the Flutter view as an RN component using a custom RNTListManager that extends RCTViewManager , exposing lifecycle methods and commands to RN.

Key RN native component registration code: /// iOS RCT_EXPORT_MODULE(FlutterListView) - (UIView *)view { if (self.viewPlugin == nil) { self.viewPlugin = [[GlobalSearchEmbedderPlugin alloc] init]; [self.viewPlugin createView]; } return self.viewPlugin.exportView; }

On Android, a SimpleViewManager creates a RNLinearLayout that hosts the Flutter fragment, with command handling for initializing the fragment and passing parameters.

/// Android class RNTListManager : SimpleViewManager () { override fun getName() = "FlutterListView" override fun createViewInstance(reactContext: ThemedReactContext) = LayoutInflater.from(reactContext).inflate(R.layout.flutter_container, null) as RNLinearLayout override fun getCommandsMap() = mapOf("setDestinationParam" to 1) override fun receiveCommand(root: RNLinearLayout, commandId: String?, args: ReadableArray?) { if (commandId?.toInt() == 1) initFlutterFragment(root.context, args) } }

Native Integration : The same embedding principle applies; a native view hierarchy directly adds the Flutter view as a child. Lifecycle is managed by attaching the Flutter view controller to the current visible view controller.

Example native view attachment: // iOS UIViewController *rootVC = (UIViewController *)[self currentVisibleViewController]; [rootVC addChildViewController:flutterViewControler];

Event handling ensures click and scroll events propagate correctly between Flutter and its parent containers, with special handling for nested scrolling scenarios.

Lifecycle coordination relies on FlutterBoost, treating Flutter pages like WebViews managed by native containers, allowing consistent start‑up, rendering, and disposal across RN and native hosts.

Conclusion : The prototype demonstrates a viable path for mixing Flutter, RN, and native UI components, offering reusable UI blocks while highlighting challenges such as smooth nested scrolling and increased integration complexity that must be addressed in future iterations.

Fluttermobile developmentNativeCross-PlatformEmbeddingReact Native
Ctrip Technology
Written by

Ctrip Technology

Official Ctrip Technology account, sharing and discussing growth.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.