Skip to content

Refactoring FlutterViewController to support addToExistingApp better #52456

@xujim

Description

@xujim

Use case

As we know, flutter was designed to only support one flutter view container in the whole app at the very beginning. As a result, the life cycle of FlutterViewController is as same as the whole app. The FlutterViewController will start, resume and pause the app life cycle state according to the view appear/disappear events. What is more, it handle the surface update process and not allowed the sub class to override.
And now, we try to support adding it to existing app, and support multiple flutter view controller sometimes.
However, due to the first design, we met a lot of problems, as following:

  1. the app's life cycle is not as same as one FlutterViewController, because we have more Flutter VC.
  2. The sequence of multiple views' life cycle have side effect on the surface updates. for example:
    I start a FlutterVC#1 to render flutter page#2, then I push a second FlutterVC#2 to render flutter page#2. The FlutterVC#2 will cover the FlutterVC#1. Note that we have only one FlutterEngine which hold only one surface, so when I started the FlutterVC#2, the FlutterVC#2 view will appear and surfaceUpdate:YES, then for a while, the FlutterVC#1 will view disappear, and surfaceUpdate:NO, which will let the FlutterEngine hold a nulled surface, and introduce failure of FlutterVC#2.

Proposal

I suggest that:

  1. refactoring the FlutterViewController to extract the sub functions occurred in view's appear and disappear event, and let those sub function public accessed by sub class.
    Take the viewWillAppear as an example:
- (void)viewWillAppear:(BOOL)animated {
  TRACE_EVENT0("flutter", "viewWillAppear");

  if (_engineNeedsLaunch) {
    [_engine.get() launchEngine:nil libraryURI:nil];
    [_engine.get() setViewController:self];
    _engineNeedsLaunch = NO;
  }

  // Send platform settings to Flutter, e.g., platform brightness.
  [self onUserSettingsChanged:nil];

  // Only recreate surface on subsequent appearances when viewport metrics are known.
  // First time surface creation is done on viewDidLayoutSubviews.
  if (_viewportMetrics.physical_width) {
    [self surfaceUpdated:YES];
  }
  [[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.inactive"];

  [super viewWillAppear:animated];
}

We can refactor it to following sub functions:

- (void)onEngineNeedsLaunch{....}//this function should be public to access by sub class
- (void)deactivateEngine{...}//public function to sub class
- (void)surfaceUpdated:(BOOL)appeared {...}//make this function public to sub class
- (int)physical_width{...}//just an example
- (void)viewWillAppear:(BOOL)animated {
  TRACE_EVENT0("flutter", "viewWillAppear");

  [self onEngineNeedsLaunch];

  // Only recreate surface on subsequent appearances when viewport metrics are known.
  // First time surface creation is done on viewDidLayoutSubviews.
  if ([self physical_width]) {
    [self surfaceUpdated:YES];
  }
  [self deactivateEngine:YES];

  [super viewWillAppear:animated];
}

Then in my MyFlutterViewController which inherit from FlutterViewController, I can decide when I need to call surfaceUpdated function during view's life cycle, and avoid to introduce the problem mentioned in problem#2.

@implementaton MYFlutterViewController : public FlutterViewController
- (void)viewWillAppear:(BOOL)animated {
  TRACE_EVENT0("myflutter", "viewWillAppear");

  [self onEngineNeedsLaunch];

  // Only recreate surface on subsequent appearances when viewport metrics are known.
  // First time surface creation is done on viewDidLayoutSubviews.
  if ([self physical_width]) {
    [self surfaceUpdated:YES];
  }
  [self deactivateEngine:YES];

// here I am able to not call super's implementation, and avoid surfaceUpdate:YES, and move this call to viewAppear handler
 // [super viewWillAppear:animated];
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projecta: existing-appsIntegration with existing apps via the add-to-app flowc: proposalA detailed proposal for a change to Fluttercustomer: alibabaengineflutter/engine related. See also e: labels.platform-iosiOS applications specificallyteam-iosOwned by iOS platform teamtriaged-iosTriaged by iOS platform team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions