Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@ngminhduong
Copy link
Contributor

Fix issue reported from ticket
flutter/flutter#50949

Copy link
Member

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existing behavior is to launch the engine only when UIKit attempts to load the Flutter view. With this patch, the engine will be loaded eagerly even when there is no need to display the same. If the application wants to launch the engine irrespective of the whether its view is being displayed, it can use the engine reference directly to launch the Flutter isolate.

Copy link
Contributor

@dnfield dnfield left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will break existing usages. If you need this behavior we should probably just create a new initializer.

We should also have a test for it.

Copy link
Member

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apologize. I was incorrect with my previous comment.

With this patch, the engine will be loaded eagerly even when there is no need to display the same.

This is exactly what you are avoiding with this patch.

The patch looks good but please add a test.

@chinmaygarde chinmaygarde self-requested a review February 19, 2020 03:17
@dnfield
Copy link
Contributor

dnfield commented Feb 19, 2020

But now the viewcontroller won't get attached to the engine right?

@chinmaygarde
Copy link
Member

But now the viewcontroller won't get attached to the engine right?

Yeah. You're right. We need to figure out why setting the view controller is implicitly loading the view. This seems like an issue where some other method missed the UIViewController.isViewLoaded check and directly accessed the view (implicitly loading it). We should figure out what that call is and fix that.

@ngminhduong
Copy link
Contributor Author

This will break existing usages. If you need this behavior we should probably just create a new initializer.

Yeah. But I think that current initializer doesn't follow iOS app lifecycle. We should correct it.

@ngminhduong
Copy link
Contributor Author

But now the viewcontroller won't get attached to the engine right?

Viewcontroller will attached to the engine in viewWillAppear

- (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];
}

Does it make something broken?

@dnfield
Copy link
Contributor

dnfield commented Feb 19, 2020

Took a little more time to read through some code here.

I'm concerned that this change would lead to calling launchEngine on an already launched engine. The call is meant to be safe for re-entrancy, but it involves jumping around some threads even to check that it's already running.

I believe our problem is that when you set the owner view controller, we access its view, which will cause it to load,here:

[static_cast<FlutterView*>(owner_controller.get().view) createSurface:gl_context_];

We should somehow instead only create the surface when the view is actually available, instead of forcing it to load there. That will avoid making unnecessary re-entrant calls to launchEngine, and also make it safe for users to call setViewController on the engine without forcing the VC to load.

_ongoingTouches = [[NSMutableSet alloc] init];

[self performCommonViewControllerInitialization];
[engine setViewController:self];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this line here is what's causing the view to load.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. That right.

@dnfield
Copy link
Contributor

dnfield commented Feb 19, 2020

A simpler way to handle this for now (without fixing the underlying problem of setting the VC causing it to load the view) would be to avoid setting the VC in the intializer, but conditionally setting it in viewWillAppear if the engine's view is nil.

That seems a little hacky though, and likely to break something in a difficult to understand way. A better resolution here should be to just have the platform view more lazily instantiate the surface it wants, only after some other action has caused the view to load (unless isViewLoaded is true).

@ngminhduong
Copy link
Contributor Author

ngminhduong commented Feb 19, 2020

@dnfield, @chinmaygarde
I updated pull request with new approach.
Can you help to review it again.
Please review the solution.
I will update unittest later.
Thanks

@ngminhduong ngminhduong force-pushed the dev/bugfix_50949 branch 2 times, most recently from ace18f3 to 46def80 Compare February 19, 2020 14:47
Comment on lines 454 to 459
if (!_isAttchedView) {
[_engine.get() attachView];
_isAttchedView = YES;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this guard? It seems like if we actually loaded a new instance of the view, we'd want to let the engine know about it to update the surface/a11y bridge.

But we would not want to let it know if the view was actually the same view.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we this guard.
Make sure that we don't create another instance of ios_surface_ in platform_view_ios.mm
I think that this is the same with old logic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fine. If this is a bug it's existing and we can address it separately

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably FML_DCHECK that owner controller is not nil here though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added FML_DCHECK.
Thanks

@dnfield
Copy link
Contributor

dnfield commented Feb 19, 2020

also /cc @gaaclarke (GitHub is slow right now and failing to let me add you as a reviewer).

_engineNeedsLaunch = NO;
}

if (!_isAttchedView) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this be more appropriate in loadView? Wouldn't that timing more match how it was previously and you wouldn't have to keep an extra bool _isViewAttached?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will loadView ever get called more than once in the lifecycle of a UIViewController?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked offline - the answer should be no

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should only be called once. We should actually use viewDidLoad since it's a bit safer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So need also call setViewController in viewDidLoad. Is that right?

Copy link
Member

@gaaclarke gaaclarke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ngminhduong
Copy link
Contributor Author

Hi @dnfield , @gaaclarke
I have some update.
Can you help to review again.

@ngminhduong
Copy link
Contributor Author

Hi have anything issues should be fixed with this patch?
Can you help to review it.
Thanks,

engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 6, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 6, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 6, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 7, 2020
cbracken pushed a commit to flutter/flutter that referenced this pull request Mar 7, 2020
* 7c612de Roll fuchsia/sdk/core/linux-amd64 from cXgMr... to cTw2C... (flutter/engine#16970)

* 6cfa7fc fix shadows and mask filter blurs (flutter/engine#16963)

* bfebadf Roll src/third_party/skia 012f8497802e..93a2a6b8badb (4 commits) (flutter/engine#16974)

* 47963a5 Roll src/third_party/skia 93a2a6b8badb..74055566bd14 (2 commits) (flutter/engine#16981)

* 98f9941 [fuchsia] fix broken flows when under high load (flutter/engine#16834)

* fe051e0 Fix issue viewdidload call while init FlutterViewController (flutter/engine#16672)

* 0ad54c2 [web] Fixes IE11 crash due to missing canvas ellipse support and font polyfill failure (flutter/engine#16965)

* f6435de Roll fuchsia/sdk/core/mac-amd64 from J6ct_... to 95geB... (flutter/engine#16982)

* 43971ca Roll src/third_party/skia 74055566bd14..54de2fa48d85 (3 commits) (flutter/engine#16983)

* 45e61a6 Roll fuchsia/sdk/core/linux-amd64 from cTw2C... to K1wwe... (flutter/engine#16984)

* 1ab5c36 Roll src/third_party/skia 54de2fa48d85..beaaf4700f50 (3 commits) (flutter/engine#16987)

* e2c0454 remove 10s timeouts from tests (flutter/engine#16988)

* dfc9c12 Roll src/third_party/skia beaaf4700f50..6e58290ba639 (9 commits) (flutter/engine#16990)

* eddda80 fushia licenses fix (flutter/engine#16992)

* c15f239 documented fluttertexture.h (flutter/engine#16950)

* e1ba7a1 Roll src/third_party/skia 6e58290ba639..24a8e9e170f7 (5 commits) (flutter/engine#16996)

* fc5963d [web] Engine integration test (flutter/engine#16930)

* d323bac doxygen tooling updates and doxygen for FlutterCodecs.h (flutter/engine#16947)

* 03ddc1d Started deleting .DS_Store files so licenses can run on mac os x. (flutter/engine#16998)

* 30a8292 Roll src/third_party/skia 24a8e9e170f7..cf573d844da6 (4 commits) (flutter/engine#17004)

* d031963 Roll fuchsia/sdk/core/mac-amd64 from 95geB... to hW33F... (flutter/engine#17006)

* 41b371d Roll fuchsia/sdk/core/linux-amd64 from K1wwe... to FGMpI... (flutter/engine#17007)

* 619acd5 Revert "fix shadows and mask filter blurs (#16963)" (flutter/engine#17008)
blasten pushed a commit to blasten/engine that referenced this pull request Mar 10, 2020

#pragma mark - UIViewController lifecycle notifications

- (void)viewWillAppear:(BOOL)animated {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that we moved a bunch of stuff out of PlatformViewIOS::SetOwnerViewController which is definitely the right thing to do. But I'm not sure I understood why the change from viewWillAppear to viewDidLoad. Strictly speaking, viewDidLoad doesn't signal intent. It'll be called even if you just do flutterViewController.view without ever trying to present the FlutterViewController and we'll end up with an IOSSurface and an AccessibilityBridge.

Is it just a convenient way of avoiding having to keep track of whether viewWillAppear was already called once per instance?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

viewDidLoad means we have a valid view we can use. It's up to the developer to make sure they avoid loading the view earlier than they should, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably. The side effects is not very obvious however. Might as well take away another foot gun.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants