Unverified Commit 9ad052a5 authored by Casey Hillers's avatar Casey Hillers Committed by GitHub

Revert "Fix Android platform view creation flow" (#109389)

Merging on red to green the build.
parent c91b4812
...@@ -179,9 +179,17 @@ class RenderAndroidView extends PlatformViewRenderBox { ...@@ -179,9 +179,17 @@ class RenderAndroidView extends PlatformViewRenderBox {
Size targetSize; Size targetSize;
do { do {
targetSize = size; targetSize = size;
_currentTextureSize = await _viewController.setSize(targetSize); if (_viewController.isCreated) {
if (_isDisposed) { _currentTextureSize = await _viewController.setSize(targetSize);
return; if (_isDisposed) {
return;
}
} else {
await _viewController.create(size: targetSize);
if (_isDisposed) {
return;
}
_currentTextureSize = targetSize;
} }
// We've resized the platform view to targetSize, but it is possible that // We've resized the platform view to targetSize, but it is possible that
// while we were resizing the render object's size was changed again. // while we were resizing the render object's size was changed again.
......
...@@ -764,33 +764,17 @@ abstract class AndroidViewController extends PlatformViewController { ...@@ -764,33 +764,17 @@ abstract class AndroidViewController extends PlatformViewController {
Future<void> _sendDisposeMessage(); Future<void> _sendDisposeMessage();
/// Sends the message to create the platform view with an initial [size]. /// Sends the message to create the platform view with an initial [size].
/// Future<void> _sendCreateMessage({Size? size});
/// Returns true if the view was actually created. In some cases (e.g.,
/// trying to create a texture-based view with a null size) creation will
/// fail and need to be re-attempted later.
Future<bool> _sendCreateMessage({Size? size});
/// Sends the message to resize the platform view to [size].
Future<Size> _sendResizeMessage(Size size);
@override
bool get awaitingCreation => _state == _AndroidViewState.waitingForSize;
@override @override
Future<void> create({Size? size}) async { Future<void> create({Size? size}) async {
assert(_state != _AndroidViewState.disposed, 'trying to create a disposed Android view'); assert(_state != _AndroidViewState.disposed, 'trying to create a disposed Android view');
assert(_state == _AndroidViewState.waitingForSize, 'Android view is already sized. View id: $viewId'); await _sendCreateMessage(size: size);
_state = _AndroidViewState.creating;
final bool created = await _sendCreateMessage(size: size); _state = _AndroidViewState.created;
for (final PlatformViewCreatedCallback callback in _platformViewCreatedCallbacks) {
if (created) { callback(viewId);
_state = _AndroidViewState.created;
for (final PlatformViewCreatedCallback callback in _platformViewCreatedCallbacks) {
callback(viewId);
}
} else {
_state = _AndroidViewState.waitingForSize;
} }
} }
...@@ -808,17 +792,7 @@ abstract class AndroidViewController extends PlatformViewController { ...@@ -808,17 +792,7 @@ abstract class AndroidViewController extends PlatformViewController {
/// ///
/// As a result, consumers are expected to clip the texture using [size], while using /// As a result, consumers are expected to clip the texture using [size], while using
/// the return value to size the texture. /// the return value to size the texture.
Future<Size> setSize(Size size) async { Future<Size> setSize(Size size);
assert(_state != _AndroidViewState.disposed, 'Android view is disposed. View id: $viewId');
if (_state == _AndroidViewState.waitingForSize) {
// Either `create` hasn't been called, or it couldn't run due to missing
// size information, so create the view now.
await create(size: size);
return size;
} else {
return _sendResizeMessage(size);
}
}
/// Sets the offset of the platform view. /// Sets the offset of the platform view.
/// ///
...@@ -998,7 +972,7 @@ class ExpensiveAndroidViewController extends AndroidViewController { ...@@ -998,7 +972,7 @@ class ExpensiveAndroidViewController extends AndroidViewController {
}) : super._(); }) : super._();
@override @override
Future<bool> _sendCreateMessage({Size? size}) async { Future<void> _sendCreateMessage({Size? size}) {
final Map<String, dynamic> args = <String, dynamic>{ final Map<String, dynamic> args = <String, dynamic>{
'id': viewId, 'id': viewId,
'viewType': _viewType, 'viewType': _viewType,
...@@ -1014,8 +988,7 @@ class ExpensiveAndroidViewController extends AndroidViewController { ...@@ -1014,8 +988,7 @@ class ExpensiveAndroidViewController extends AndroidViewController {
paramsByteData.lengthInBytes, paramsByteData.lengthInBytes,
); );
} }
await SystemChannels.platform_views.invokeMethod<void>('create', args); return SystemChannels.platform_views.invokeMethod<void>('create', args);
return true;
} }
@override @override
...@@ -1032,7 +1005,7 @@ class ExpensiveAndroidViewController extends AndroidViewController { ...@@ -1032,7 +1005,7 @@ class ExpensiveAndroidViewController extends AndroidViewController {
} }
@override @override
Future<Size> _sendResizeMessage(Size size) { Future<Size> setSize(Size size) {
throw UnimplementedError('Not supported for $SurfaceAndroidViewController.'); throw UnimplementedError('Not supported for $SurfaceAndroidViewController.');
} }
...@@ -1071,7 +1044,8 @@ class TextureAndroidViewController extends AndroidViewController { ...@@ -1071,7 +1044,8 @@ class TextureAndroidViewController extends AndroidViewController {
Offset _off = Offset.zero; Offset _off = Offset.zero;
@override @override
Future<Size> _sendResizeMessage(Size size) async { Future<Size> setSize(Size size) async {
assert(_state != _AndroidViewState.disposed, 'Android view is disposed. View id: $viewId');
assert(_state != _AndroidViewState.waitingForSize, 'Android view must have an initial size. View id: $viewId'); assert(_state != _AndroidViewState.waitingForSize, 'Android view must have an initial size. View id: $viewId');
assert(size != null); assert(size != null);
assert(!size.isEmpty); assert(!size.isEmpty);
...@@ -1090,6 +1064,16 @@ class TextureAndroidViewController extends AndroidViewController { ...@@ -1090,6 +1064,16 @@ class TextureAndroidViewController extends AndroidViewController {
return Size(meta!['width']! as double, meta['height']! as double); return Size(meta!['width']! as double, meta['height']! as double);
} }
@override
Future<void> create({Size? size}) async {
if (size == null) {
return;
}
assert(_state == _AndroidViewState.waitingForSize, 'Android view is already sized. View id: $viewId');
assert(!size.isEmpty);
return super.create(size: size);
}
@override @override
Future<void> setOffset(Offset off) async { Future<void> setOffset(Offset off) async {
if (off == _off) { if (off == _off) {
...@@ -1116,9 +1100,9 @@ class TextureAndroidViewController extends AndroidViewController { ...@@ -1116,9 +1100,9 @@ class TextureAndroidViewController extends AndroidViewController {
} }
@override @override
Future<bool> _sendCreateMessage({Size? size}) async { Future<void> _sendCreateMessage({Size? size}) async {
if (size == null) { if (size == null) {
return false; return;
} }
assert(!size.isEmpty, 'trying to create $TextureAndroidViewController without setting a valid size.'); assert(!size.isEmpty, 'trying to create $TextureAndroidViewController without setting a valid size.');
...@@ -1139,7 +1123,6 @@ class TextureAndroidViewController extends AndroidViewController { ...@@ -1139,7 +1123,6 @@ class TextureAndroidViewController extends AndroidViewController {
); );
} }
_textureId = await SystemChannels.platform_views.invokeMethod<int>('create', args); _textureId = await SystemChannels.platform_views.invokeMethod<int>('create', args);
return true;
} }
@override @override
...@@ -1236,15 +1219,6 @@ abstract class PlatformViewController { ...@@ -1236,15 +1219,6 @@ abstract class PlatformViewController {
/// * [PlatformViewsRegistry], which is a helper for managing platform view IDs. /// * [PlatformViewsRegistry], which is a helper for managing platform view IDs.
int get viewId; int get viewId;
/// True if [create] has not been successfully called the platform view.
///
/// This can indicate either that [create] was never called, or that [create]
/// was deferred for implementation-specific reasons.
///
/// A `false` return value does not necessarily indicate that the [Future]
/// returned by [create] has completed, only that creation has been started.
bool get awaitingCreation => false;
/// Dispatches the `event` to the platform view. /// Dispatches the `event` to the platform view.
Future<void> dispatchPointerEvent(PointerEvent event); Future<void> dispatchPointerEvent(PointerEvent event);
......
...@@ -871,20 +871,14 @@ class _PlatformViewLinkState extends State<PlatformViewLink> { ...@@ -871,20 +871,14 @@ class _PlatformViewLinkState extends State<PlatformViewLink> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final PlatformViewController? controller = _controller; if (_controller == null) {
if (controller == null) {
return const SizedBox.expand(); return const SizedBox.expand();
} }
if (!_platformViewCreated) { if (!_platformViewCreated) {
// Depending on the implementation, the initial size can be used to size // Depending on the platform, the initial size can be used to size the platform view.
// the platform view. return _PlatformViewPlaceHolder(onLayout: (Size size) => _controller!.create(size: size));
return _PlatformViewPlaceHolder(onLayout: (Size size) {
if (controller.awaitingCreation) {
controller.create(size: size);
}
});
} }
_surface ??= widget._surfaceFactory(context, controller); _surface ??= widget._surfaceFactory(context, _controller!);
return Focus( return Focus(
focusNode: _focusNode, focusNode: _focusNode,
onFocusChange: _handleFrameworkFocusChanged, onFocusChange: _handleFrameworkFocusChanged,
......
...@@ -45,16 +45,11 @@ class FakePlatformViewController extends PlatformViewController { ...@@ -45,16 +45,11 @@ class FakePlatformViewController extends PlatformViewController {
} }
class FakeAndroidViewController implements AndroidViewController { class FakeAndroidViewController implements AndroidViewController {
FakeAndroidViewController(this.viewId, {this.requiresSize = false}); FakeAndroidViewController(this.viewId);
bool disposed = false; bool disposed = false;
bool focusCleared = false; bool focusCleared = false;
bool created = false; bool created = false;
// If true, [create] won't be considered to have been called successfully
// unless it includes a size.
bool requiresSize;
bool _createCalledSuccessfully = false;
/// Events that are dispatched. /// Events that are dispatched.
List<PointerEvent> dispatchedPointerEvents = <PointerEvent>[]; List<PointerEvent> dispatchedPointerEvents = <PointerEvent>[];
...@@ -97,9 +92,6 @@ class FakeAndroidViewController implements AndroidViewController { ...@@ -97,9 +92,6 @@ class FakeAndroidViewController implements AndroidViewController {
@override @override
int get textureId => 0; int get textureId => 0;
@override
bool get awaitingCreation => !_createCalledSuccessfully;
@override @override
bool get isCreated => created; bool get isCreated => created;
...@@ -122,10 +114,7 @@ class FakeAndroidViewController implements AndroidViewController { ...@@ -122,10 +114,7 @@ class FakeAndroidViewController implements AndroidViewController {
} }
@override @override
Future<void> create({Size? size}) async { Future<void> create({Size? size}) async {}
assert(!_createCalledSuccessfully);
_createCalledSuccessfully = size != null || !requiresSize;
}
@override @override
List<PlatformViewCreatedCallback> get createdCallbacks => <PlatformViewCreatedCallback>[]; List<PlatformViewCreatedCallback> get createdCallbacks => <PlatformViewCreatedCallback>[];
......
...@@ -1026,7 +1026,6 @@ void main() { ...@@ -1026,7 +1026,6 @@ void main() {
containerFocusNode.requestFocus(); containerFocusNode.requestFocus();
viewsController.createCompleter!.complete();
await tester.pump(); await tester.pump();
expect(containerFocusNode.hasFocus, isTrue); expect(containerFocusNode.hasFocus, isTrue);
...@@ -2424,110 +2423,7 @@ void main() { ...@@ -2424,110 +2423,7 @@ void main() {
onCreatePlatformView: (PlatformViewCreationParams params) { onCreatePlatformView: (PlatformViewCreationParams params) {
onPlatformViewCreatedCallBack = params.onPlatformViewCreated; onPlatformViewCreatedCallBack = params.onPlatformViewCreated;
createdPlatformViewId = params.id; createdPlatformViewId = params.id;
return FakePlatformViewController(params.id)..create(); return FakePlatformViewController(params.id);
},
surfaceFactory: (BuildContext context, PlatformViewController controller) {
return PlatformViewSurface(
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
controller: controller,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
);
await tester.pumpWidget(platformViewLink);
expect(
tester.allWidgets.map((Widget widget) => widget.runtimeType.toString()).toList(),
equals(<String>['PlatformViewLink', '_PlatformViewPlaceHolder']),
);
onPlatformViewCreatedCallBack(createdPlatformViewId);
await tester.pump();
expect(
tester.allWidgets.map((Widget widget) => widget.runtimeType.toString()).toList(),
equals(<String>['PlatformViewLink', 'Focus', '_FocusMarker', 'Semantics', 'PlatformViewSurface']),
);
expect(createdPlatformViewId, currentViewId + 1);
},
);
testWidgets(
'PlatformViewLink calls create when needed for Android texture display modes',
(WidgetTester tester) async {
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
late int createdPlatformViewId;
late PlatformViewCreatedCallback onPlatformViewCreatedCallBack;
late PlatformViewController controller;
final PlatformViewLink platformViewLink = PlatformViewLink(
viewType: 'webview',
onCreatePlatformView: (PlatformViewCreationParams params) {
onPlatformViewCreatedCallBack = params.onPlatformViewCreated;
createdPlatformViewId = params.id;
controller = FakeAndroidViewController(params.id, requiresSize: true);
controller.create();
// This test should be simulating one of the texture-based display
// modes, where `create` is a no-op when not provided a size, and
// creation is triggered via a later call to setSize, or to `create`
// with a size.
expect(controller.awaitingCreation, true);
return controller;
},
surfaceFactory: (BuildContext context, PlatformViewController controller) {
return PlatformViewSurface(
gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{},
controller: controller,
hitTestBehavior: PlatformViewHitTestBehavior.opaque,
);
},
);
await tester.pumpWidget(platformViewLink);
expect(
tester.allWidgets.map((Widget widget) => widget.runtimeType.toString()).toList(),
equals(<String>['PlatformViewLink', '_PlatformViewPlaceHolder']),
);
onPlatformViewCreatedCallBack(createdPlatformViewId);
await tester.pump();
expect(
tester.allWidgets.map((Widget widget) => widget.runtimeType.toString()).toList(),
equals(<String>['PlatformViewLink', 'Focus', '_FocusMarker', 'Semantics', 'PlatformViewSurface']),
);
expect(createdPlatformViewId, currentViewId + 1);
expect(controller.awaitingCreation, false);
},
);
testWidgets(
'PlatformViewLink does not double-call create for Android Hybrid Composition',
(WidgetTester tester) async {
final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
late int createdPlatformViewId;
late PlatformViewCreatedCallback onPlatformViewCreatedCallBack;
late PlatformViewController controller;
final PlatformViewLink platformViewLink = PlatformViewLink(
viewType: 'webview',
onCreatePlatformView: (PlatformViewCreationParams params) {
onPlatformViewCreatedCallBack = params.onPlatformViewCreated;
createdPlatformViewId = params.id;
controller = FakeAndroidViewController(params.id);
controller.create();
// This test should be simulating Hybrid Composition mode, where
// `create` takes effect immidately.
expect(controller.awaitingCreation, false);
return controller;
}, },
surfaceFactory: (BuildContext context, PlatformViewController controller) { surfaceFactory: (BuildContext context, PlatformViewController controller) {
return PlatformViewSurface( return PlatformViewSurface(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment