Mobile Development 18 min read

Integrating Flutter Map Plugin in a FlutterBoost Hybrid Project: Architecture, Issues, and Solutions

This article explains how to integrate the Baidu map plugin into a FlutterBoost hybrid project, describes the PlatformView mechanism, analyzes rendering and thread‑synchronization details, and provides concrete solutions for iOS white‑screen, Android freeze, memory‑leak, custom markers and visible‑range problems.

Ctrip Technology
Ctrip Technology
Ctrip Technology
Integrating Flutter Map Plugin in a FlutterBoost Hybrid Project: Architecture, Issues, and Solutions

Background – With the rapid growth of multi‑platform technologies, Ctrip’s projects have evolved from pure native to Native+ReactNative and now Native+ReactNative+Flutter. Because the business relies on the Flutter stack, a nested map display is required. Two main approaches exist: using the official Flutter map plugin or embedding a native map via PlatformView.

Why choose the official plugin – Although native maps are mature, embedding them in Flutter would require custom containers and extensive bridge code on both Android and iOS, increasing maintenance cost. Therefore the team opted for source‑code integration of the Flutter map plugin, focusing on a Flutter‑Boost hybrid project.

How to integrate the source code

Flutter side – Download the official demo, run flutter pub get , locate the pub‑cache directory, and copy the required src files into the Flutter project.

iOS side – After flutter pub get , import the iOS/Classes/ folder of the plugin into the Xcode project.

Android side – Create a new map module in the native project and copy the Android part of the plugin source into it.

Map plugin implementation principle – PlatformView

The plugin is divided into Map, Search, Util modules and communicates with native via MethodChannel . It uses PlatformView to embed the native map into Flutter pages (UIKitView on iOS, AndroidView on Android). The native side creates a BMFMapViewController that aggregates map operations and forwards them through the channel.

What is PlatformView – PlatformView allows native UI components (e.g., maps, WebView) to be displayed inside a Flutter widget. Flutter provides two implementations: Virtual Display and Hybrid Composition. iOS uses Hybrid Composition; Android supports both.

PlatformView rendering flow

After receiving a VSync signal, Dart updates the Widget, Element and RenderObject trees, builds a LayerTree, and passes it to the Engine. For PlatformView, a PlatformViewLayer is created, which records view ID, size and position, and the native view is composited during the rasterization phase.

void FlutterPlatformViewsController::OnCreate(FlutterMethodCall* call, FlutterResult& result) {
NSDictionary<NSString*, id>* args = [call arguments];
long viewId = [args[@"id"] longValue];
NSObject<FlutterPlatformView>* embedded_view = [factory createWithFrame:CGRectZero viewIdentifier:viewId arguments:params];
UIView* platform_view = [embedded_view view];
// ... cache the view ...
}

During rasterization, PlatformViewLayer::Preroll marks the frame as containing a PlatformView and passes the view parameters to the engine.

void PlatformViewLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
set_paint_bounds(SkRect::MakeXYWH(offset_.x(), offset_.y(), size_.width(), size_.height()));
context->has_platform_view = true;
// ... create EmbeddedViewParams and composite ...
}

Frame synchronization – Flutter merges the Raster thread with the Platform thread when a PlatformView is present, ensuring that both native and Flutter rendering happen on the same thread and thus stay in sync.

PostPrerollResult FlutterPlatformViewsController::PostPrerollAction(fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
if (!HasPlatformViewThisOrNextFrame()) return PostPrerollResult::kSuccess;
if (!raster_thread_merger->IsMerged()) { CancelFrame(); return PostPrerollResult::kSkipAndRetryFrame; }
BeginCATransaction();
raster_thread_merger->ExtendLeaseTo(kDefaultMergedLeaseDuration);
return PostPrerollResult::kSuccess;
}

Problems and solutions

iOS white‑screen when switching pages – The PlatformView is recreated after viewDidLayoutSubviews and surfaceUpdated . Moving the surfaceUpdated call to viewWillAppear (or calling the super implementation) fixes the issue.

Android map freeze after returning from another page – The context becomes null because PlatformViewsController.detach() clears it. Setting shouldAttachEngineToActivity() to false keeps the engine alive across activities.

Android memory leak – Repeatedly opening the map creates dangling PlatformViewsHandler references. Delaying the null‑assignment until after the map view is disposed (using a guard flag) prevents the leak.

Custom bitmap marker – Use PictureRecorder and Canvas to draw text and images, then convert to PNG bytes and pass them via the channel. Ensure the size is in physical pixels.

Show all markers within visible bounds – Compute the northeast and southwest coordinates of all markers, then call setVisibleMapRectWithPadding . Adjust padding for Android by scaling with devicePixelRatio .

Conclusion – The Flutter map plugin is a thin wrapper over native SDKs, using MethodChannel and PlatformView to provide map display, interaction, overlay drawing and event handling. In hybrid projects most integration problems stem from PlatformView lifecycle and thread‑synchronization issues, which can be mitigated by proper engine management, careful handling of detach/attach callbacks, and using tools like LeakCanary for memory diagnostics.

FluttermobileflutterboostiOSAndroidmapplatformview
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.