Mobile Development 13 min read

Implementation of a Hybrid Flutter Container for Page Routing in Native Apps

This article explains the design and implementation of a hybrid Flutter container for native Android and iOS apps, covering concept overview, solution comparison, container stack management, navigation handling, iOS gesture support, multi‑container strategies, routing protocols, and practical code examples.

Beike Product & Technology
Beike Product & Technology
Beike Product & Technology
Implementation of a Hybrid Flutter Container for Page Routing in Native Apps

When a pure Flutter app manages its own page routing, integrating Flutter into an existing native app requires a separate routing mechanism to switch between native and Flutter pages. This article introduces the implementation of the Beike Flutter container, discussing solution selection, container stack management, Flutter navigation stack handling, and practical issues encountered.

1. Flutter Related Concepts

Page : In Flutter a page is a Route ; on Android it corresponds to an Activity , and on iOS to a ViewController .

Flutter Container : Provides a runtime environment for Dart code and typically consists of three parts:

FlutterActivity / FlutterViewController – the base classes for displaying Flutter pages (Android and iOS respectively).

FlutterView – the view that renders Flutter widgets.

FlutterEngine – a portable runtime that hosts the Flutter application, including core libraries, plugin architecture, and the Dart VM.

initialRoute : Identifier of a Flutter page route.

Navigator : Manages Route objects via an overlay stack.

2. Solution Research

We compared the official Flutter integration with Alibaba’s FlutterBoost (used by Xianyu) and performed demos on route management.

2.1 Official vs. FlutterBoost

Comparison Item

FlutterBoost‑v0.1.64

Flutter Official‑v1.12.13

Flutter Engine Sharing

Y

Y (does not support dynamic initialRoute)

Arbitrary hybrid page navigation

Y

Y (non‑shared engine)

Consistent page lifecycle for multiple Flutter pages

Y

N

Data passing between pages (return values)

Y

N

Support for side‑swipe gestures

N

Y (iOS side‑swipe, Android via back key)

Support for cross‑page hero animation

Y

Y

Consistent Route scheme

Y

Y (initialRoute)

Version upgrade adaptation cost

High

Low

2.2 Route Management Research

Modify the underlying Engine code to enable dynamic route passing – rejected due to native changes and uncertain stability.

Use a MethodChannel to pass initialRoute ahead of time – deemed to have little advantage.

Delegate route handling to a custom NavigatorManager during container lifecycle – the approach adopted by FlutterBoost and chosen for its stability.

2.3 Solution Determination

Official container solutions require minimal customization but cannot dynamically replace initialRoute when the Engine is shared. FlutterBoost offers richer features and Engine sharing but incurs higher version‑upgrade costs. The final decision was to use the official shared‑Engine approach for the overall architecture while borrowing FlutterBoost’s routing implementation.

3. Container Implementation

3.1 Overall Architecture

The architecture diagram (omitted) shows the interaction between native containers, the shared FlutterEngine , and the custom navigation manager.

3.2 Android Container Stack Management

Containers implementing IFlutterViewContainer are cached in a stack. The Flutter side accesses a container via a unique ID.

public interface IFlutterViewContainer {
    String uniqueId();

    String initialRoute();
    // Current Flutter page's Activity
    Activity getContainerActivity();
    // Provide data
    void finishContainer(Map
result);
    // Receive data
    void onContainerResult(int requestCode, int resultCode, Intent data);
}

Issue: the default back‑key triggers NavigationChannel.popRoute() , which exits the app when multiple containers exist. The solution intercepts the back event and forwards it through a custom channel:

void onBackPressed() {
    ensureAlive();
    if (flutterEngine != null) {
        Log.v(TAG, "Forwarding onBackPressed() to FlutterEngine.");
        flutterEngine.getNavigationChannel().popRoute();
    } else {
        Log.w(TAG, "Invoked onBackPressed() before FlutterFragment was attached to an Activity.");
    }
}

In the custom activity:

public class RunnerFlutterActivity extends FlutterActivity implements IFlutterViewContainer {
    @Override
    public void onBackPressed() {
        // super.onBackPressed();
        invokeChannelWithParams("onBackPressed");
    }
}

3.3 iOS Side‑Swipe Back Support

Two scenarios cause side‑swipe failure. The fix involves monitoring the Navigator stack in Dart and notifying iOS to enable/disable the gesture.

class IosGestureObserver extends NavigatorObserver {
  @override
  void didPush(Route route, Route previousRoute) {
    if (route.navigator.canPop()) {
      // Notify Native to Disable navigation Gesture
    }
    super.didPush(route, previousRoute);
  }

  @override
  void didPop(Route route, Route previousRoute) {
    if (!previousRoute.navigator.canPop()) {
      // Notify Native to Enable navigation Gesture
    }
    super.didPop(route, previousRoute);
  }
}

Native side receives the notification and adjusts the interactive pop gesture accordingly:

- (void)notificationEnableUserGesture:(NSNotification *)notification {
    NSDictionary *userInfo = notification.userInfo;
    NSNumber *enableNumber = userInfo[@"enableUserGesture"];
    self.flutterCanPop = [enableNumber boolValue];
    if ([self.delegate respondsToSelector:@selector(flutterPagePopStateChange:)]) {
        [self.delegate flutterViewController:self PagePopStateChange:self.flutterCanPop];
    } else {
        if (self.originCanPop) {
            self.navigationController.interactivePopGestureRecognizer.enabled = !self.flutterCanPop;
        }
    }
    return;
}

@protocol BKFlutterViewControllerDelegate
- (void)flutterViewController:(BKFlutterViewController *)viewController PagePopStateChange:(BOOL)canPop;
@end

3.4 Multi‑Container Navigator Stack Management

In multi‑engine, multi‑container scenarios each container has its own Navigator , which incurs memory overhead. A single‑engine, multi‑container solution copies the container’s uniqueId and route table into a custom RunnerNavigator , records it as an OverlayEntry , and binds native containers to Flutter routes via the ID.

3.5 Flutter Page Routing Protocol

The container supports two parameter formats:

lianjialink://flutter/page?flutter_url=my/flutter/page&tel=10086&city=bj
lianjialink://flutter/page?flutter_url=my/flutter/page&params={"tel":10086,"city":"bj"}

The protocol consists of a route header, fixed keys (e.g., flutter_url ), and business parameters either as query strings or JSON.

3.6 Android Flutter Fragment

Because the official FlutterFragment cannot set dynamic routes with a shared Engine, we ported the shared‑Engine logic from Activity to Fragment . The exposed API mirrors the Activity usage:

IOperationCallback router = new IOperationCallback() {
    @Override
    public void openContainer(Context context, String url, Map
urlParams, int requestCode) {
        // Flutter activity startActivity/ForResult
    }

    @Override
    public void openContainerFromFragment(Fragment fragment, String url, Map
urlParams, int requestCode) {
        // Flutter fragment startActivity/ForResult
    }
};

4. Summary

The hybrid container solution has been deployed in the Beike app and the Real‑Estate Consultant app, showing good performance and stability. It addresses issues such as repeated network requests caused by Flutter build() and iOS side‑swipe failures. Future work includes supporting Android broadcasts and iOS notification‑center features.

5. References

Flutter Add‑to‑App Documentation

FlutterBoost GitHub Repository

Flutterhybrid appiOSAndroidcontainerrouting
Beike Product & Technology
Written by

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.

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.