未验证 提交 9004af13 编写于 作者: D Dan Field 提交者: GitHub

Allow FlutterViewController to be released when not initialized with an engine (#6879)

* Break cycle between FlutterViewController and FlutterEngine
上级 9d206e27
......@@ -8,6 +8,9 @@
/**
BREAKING CHANGES:
December 17, 2018:
- Changed designated initializer on FlutterEngine
October 5, 2018:
- Removed FlutterNavigationController.h/.mm
- Changed return signature of `FlutterDartHeadlessCodeRunner.run*` from void
......
......@@ -55,8 +55,28 @@ FLUTTER_EXPORT
* the threads used by this FlutterEngine.
* @param projectOrNil The `FlutterDartProject` to run.
*/
- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil;
/**
* Initialize this FlutterEngine with a `FlutterDartProject`.
*
* If the FlutterDartProject is not specified, the FlutterEngine will attempt to locate
* the project in a default location (the flutter_assets folder in the iOS application
* bundle).
*
* A newly initialized engine will not run the `FlutterDartProject` until either
* `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI:` is called.
*
* @param labelPrefix The label prefix used to identify threads for this instance. Should
* be unique across FlutterEngine instances, and is used in instrumentation to label
* the threads used by this FlutterEngine.
* @param projectOrNil The `FlutterDartProject` to run.
* @param allowHeadlessExecution Whether or not to allow this instance to continue
* running after passing a nil `FlutterViewController` to `-setViewController:`.
*/
- (instancetype)initWithName:(NSString*)labelPrefix
project:(FlutterDartProject*)projectOrNil NS_DESIGNATED_INITIALIZER;
project:(FlutterDartProject*)projectOrNil
allowHeadlessExecution:(BOOL)allowHeadlessExecution NS_DESIGNATED_INITIALIZER;
/**
* The default initializer is not available for this object.
......
......@@ -46,8 +46,25 @@ FLUTTER_DEPRECATED("FlutterEngine should be used rather than FlutterHeadlessDart
* be unique across FlutterEngine instances
* @param projectOrNil The `FlutterDartProject` to run.
*/
- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil;
/**
* Iniitalize this FlutterHeadlessDartRunner with a `FlutterDartProject`.
*
* If the FlutterDartProject is not specified, the FlutterHeadlessDartRunner will attempt to locate
* the project in a default location.
*
* A newly initialized engine will not run the `FlutterDartProject` until either
* `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI` is called.
*
* @param labelPrefix The label prefix used to identify threads for this instance. Should
* be unique across FlutterEngine instances
* @param projectOrNil The `FlutterDartProject` to run.
* @param allowHeadlessExecution Must be set to `YES`.
*/
- (instancetype)initWithName:(NSString*)labelPrefix
project:(FlutterDartProject*)projectOrNil NS_DESIGNATED_INITIALIZER;
project:(FlutterDartProject*)projectOrNil
allowHeadlessExecution:(BOOL)allowHeadlessExecution NS_DESIGNATED_INITIALIZER;
/**
* Not recommended for use - will initialize with a default label ("io.flutter.headless")
......
......@@ -151,6 +151,11 @@ FLUTTER_EXPORT
*/
@property(nonatomic, getter=isViewOpaque) BOOL viewOpaque;
/**
* The `FlutterEngine` instance for this view controller.
*/
@property(weak, nonatomic, readonly) FlutterEngine* engine;
@end
#endif // FLUTTER_FLUTTERVIEWCONTROLLER_H_
......@@ -60,12 +60,22 @@
fml::scoped_nsobject<FlutterBasicMessageChannel> _settingsChannel;
int64_t _nextTextureId;
BOOL _allowHeadlessExecution;
}
- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil {
return [self initWithName:labelPrefix project:projectOrNil allowHeadlessExecution:YES];
}
- (instancetype)initWithName:(NSString*)labelPrefix
project:(FlutterDartProject*)projectOrNil
allowHeadlessExecution:(BOOL)allowHeadlessExecution {
self = [super init];
NSAssert(self, @"Super init cannot be nil");
NSAssert(labelPrefix, @"labelPrefix is required");
_allowHeadlessExecution = allowHeadlessExecution;
_labelPrefix = [labelPrefix copy];
_weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterEngine>>(self);
......@@ -76,7 +86,6 @@
_dartProject.reset([projectOrNil retain]);
_pluginPublications = [NSMutableDictionary new];
_publisher.reset([[FlutterObservatoryPublisher alloc] init]);
_platformViewsController.reset(new shell::FlutterPlatformViewsController());
[self setupChannels];
......@@ -135,7 +144,14 @@
FML_DCHECK(self.iosPlatformView);
_viewController = [viewController getWeakPtr];
self.iosPlatformView->SetOwnerViewController(_viewController);
[self maybeSetupPlatformViewChannels];
if (!viewController && !_allowHeadlessExecution) {
[self resetChannels];
_shell.reset();
_threadHost.Reset();
} else {
[self maybeSetupPlatformViewChannels];
}
}
- (FlutterViewController*)viewController {
......@@ -176,6 +192,20 @@
return _settingsChannel.get();
}
- (void)resetChannels {
_localizationChannel.reset();
_navigationChannel.reset();
_platformChannel.reset();
_platformViewsChannel.reset();
_textInputChannel.reset();
_lifecycleChannel.reset();
_systemChannel.reset();
_settingsChannel.reset();
}
// If you add a channel, be sure to also update `resetChannels`.
// Channels get a reference to the engine, and therefore need manual
// cleanup for proper collection.
- (void)setupChannels {
_localizationChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/localization"
......@@ -221,8 +251,6 @@
_textInputPlugin.get().textInputDelegate = self;
_platformPlugin.reset([[FlutterPlatformPlugin alloc] initWithEngine:[self getWeakPtr]]);
[self maybeSetupPlatformViewChannels];
}
- (void)maybeSetupPlatformViewChannels {
......@@ -348,6 +376,11 @@
FML_LOG(ERROR) << "Could not start a shell FlutterEngine with entrypoint: "
<< entrypoint.UTF8String;
} else {
[self setupChannels];
if (!_platformViewsController) {
_platformViewsController.reset(new shell::FlutterPlatformViewsController());
}
_publisher.reset([[FlutterObservatoryPublisher alloc] init]);
[self maybeSetupPlatformViewChannels];
}
......
......@@ -28,7 +28,17 @@
}
- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil {
return [super initWithName:labelPrefix project:projectOrNil];
return [self initWithName:labelPrefix project:projectOrNil allowHeadlessExecution:YES];
}
- (instancetype)initWithName:(NSString*)labelPrefix
project:(FlutterDartProject*)projectOrNil
allowHeadlessExecution:(BOOL)allowHeadlessExecution {
NSAssert(allowHeadlessExecution == YES,
@"Cannot initialize a FlutterHeadlessDartRunner without headless execution.");
return [super initWithName:labelPrefix
project:projectOrNil
allowHeadlessExecution:allowHeadlessExecution];
}
- (instancetype)init {
return [self initWithName:@"io.flutter.headless" project:nil];
......
......@@ -67,7 +67,9 @@
if (self) {
_viewOpaque = YES;
_weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterViewController>>(self);
_engine.reset([[FlutterEngine alloc] initWithName:@"io.flutter" project:projectOrNil]);
_engine.reset([[FlutterEngine alloc] initWithName:@"io.flutter"
project:projectOrNil
allowHeadlessExecution:NO]);
_flutterView.reset([[FlutterView alloc] initWithDelegate:_engine opaque:self.isViewOpaque]);
[_engine.get() createShell:nil libraryURI:nil];
_engineNeedsLaunch = YES;
......@@ -116,8 +118,8 @@
[self setupNotificationCenterObservers];
}
- (fml::scoped_nsobject<FlutterEngine>)engine {
return _engine;
- (FlutterEngine*)engine {
return _engine.get();
}
- (fml::WeakPtr<FlutterViewController>)getWeakPtr {
......@@ -389,9 +391,9 @@
if (_engineNeedsLaunch) {
[_engine.get() launchEngine:nil libraryURI:nil];
[_engine.get() setViewController:self];
_engineNeedsLaunch = NO;
}
[_engine.get() setViewController:self];
// Only recreate surface on subsequent appearances when viewport metrics are known.
// First time surface creation is done on viewDidLayoutSubviews.
......@@ -423,7 +425,7 @@
TRACE_EVENT0("flutter", "viewDidDisappear");
[self surfaceUpdated:NO];
[[_engine.get() lifecycleChannel] sendMessage:@"AppLifecycleState.paused"];
[_engine.get() setViewController:nil];
[super viewDidDisappear:animated];
}
......
......@@ -17,8 +17,6 @@
- (fml::WeakPtr<FlutterViewController>)getWeakPtr;
- (shell::FlutterPlatformViewsController*)platformViewsController;
@property(readonly) fml::scoped_nsobject<FlutterEngine> engine;
@end
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册