Wait for non-empty layout in platform view placeholder (#112402) (#113040)

Co-authored-by: Kevin Chisholm <kevinjchisholm@google.com>
Co-authored-by: godofredoc <godofredoc@google.com>
diff --git a/packages/flutter/lib/src/widgets/platform_view.dart b/packages/flutter/lib/src/widgets/platform_view.dart
index 0a9721f..798ef09 100644
--- a/packages/flutter/lib/src/widgets/platform_view.dart
+++ b/packages/flutter/lib/src/widgets/platform_view.dart
@@ -869,10 +869,10 @@
       return const SizedBox.expand();
     }
     if (!_platformViewCreated) {
-      // Depending on the implementation, the initial size can be used to size
-      // the platform view.
+      // Depending on the implementation, the first non-empty size can be used
+      // to size the platform view.
       return _PlatformViewPlaceHolder(onLayout: (Size size) {
-        if (controller.awaitingCreation) {
+        if (controller.awaitingCreation && !size.isEmpty) {
           controller.create(size: size);
         }
       });
diff --git a/packages/flutter/test/services/fake_platform_views.dart b/packages/flutter/test/services/fake_platform_views.dart
index 5210478..0d80150 100644
--- a/packages/flutter/test/services/fake_platform_views.dart
+++ b/packages/flutter/test/services/fake_platform_views.dart
@@ -124,6 +124,9 @@
   @override
   Future<void> create({Size? size}) async {
     assert(!_createCalledSuccessfully);
+    if (requiresSize && size != null) {
+      assert(!size.isEmpty);
+    }
     _createCalledSuccessfully = size != null || !requiresSize;
   }
 
diff --git a/packages/flutter/test/widgets/platform_view_test.dart b/packages/flutter/test/widgets/platform_view_test.dart
index 7c15a7b..e503219 100644
--- a/packages/flutter/test/widgets/platform_view_test.dart
+++ b/packages/flutter/test/widgets/platform_view_test.dart
@@ -2456,6 +2456,48 @@
     );
 
     testWidgets(
+      'PlatformViewLink widget should not trigger creation with an empty size',
+      (WidgetTester tester) async {
+        late PlatformViewController controller;
+
+        final Widget widget = Center(child: SizedBox(
+          height: 0,
+          child: PlatformViewLink(
+            viewType: 'webview',
+            onCreatePlatformView: (PlatformViewCreationParams params) {
+              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(widget);
+
+        expect(
+          tester.allWidgets.map((Widget widget) => widget.runtimeType.toString()).toList(),
+          equals(<String>['Center', 'SizedBox', 'PlatformViewLink', '_PlatformViewPlaceHolder']),
+        );
+
+        // 'create' should not have been called by PlatformViewLink, since its
+        // size is empty.
+        expect(controller.awaitingCreation, true);
+      },
+    );
+
+    testWidgets(
       'PlatformViewLink calls create when needed for Android texture display modes',
       (WidgetTester tester) async {
         final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
@@ -2494,6 +2536,9 @@
           equals(<String>['PlatformViewLink', '_PlatformViewPlaceHolder']),
         );
 
+        // Layout should have triggered a create call. Simulate the callback
+        // that the real controller would make after creation.
+        expect(controller.awaitingCreation, false);
         onPlatformViewCreatedCallBack(createdPlatformViewId);
 
         await tester.pump();
@@ -2504,7 +2549,6 @@
         );
 
         expect(createdPlatformViewId, currentViewId + 1);
-        expect(controller.awaitingCreation, false);
       },
     );