[webview_flutter_android][webview_flutter_wkwebview] Fixes bug where `PlatformWebViewWidget` doesn't rebuild when the controller changes (#4533)

In a scenario where a `WebViewWidget` was updated with a new `WebViewController`, the native `WebView` from the new controller would not be shown. e.g.

```dart
 class WebViewExample extends StatefulWidget {
  const WebViewExample({super.key});

  @override
  State<WebViewExample> createState() => _WebViewExampleState();
}

class _WebViewExampleState extends State<WebViewExample> {
  late WebViewController controller;

  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(Uri.parse('https://flutter.dev'));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Flutter Simple Example')),
      body: WebViewWidget(controller: controller),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            controller = WebViewController()
              ..loadRequest(Uri.parse('https://google.com'));
          });
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}                                                                                                                                                                                                    
```

From testing, the `WebViewWidget` would continue showing the original `WebViewController` and eventually freeze the PlatformView preventing button presses. 

This is because the PlatformView widget only creates the native PlatformView once and doesn't recreate it when the creation parameters change (as expected). This adds a default `key` to the `PlatformWebViewWidget` that is used to indicate when the underlying widget needs to be removed and recreated. See https://api.flutter.dev/flutter/widgets/Widget/key.html
diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md
index 7a02dcf..03f1539 100644
--- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md
+++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 3.9.2
+
+* Fixes bug where `PlatformWebViewWidget` doesn't rebuild when the controller or PlatformView
+  implementation flag changes. 
+
 ## 3.9.1
 
 * Adjusts SDK checks for better testability.
diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart
index 7c5f092..3761dd2 100644
--- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart
+++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart
@@ -744,6 +744,25 @@
   ///
   /// Defaults to false.
   final bool displayWithHybridComposition;
+
+  @override
+  int get hashCode => Object.hash(
+        controller,
+        layoutDirection,
+        displayWithHybridComposition,
+        platformViewsServiceProxy,
+        instanceManager,
+      );
+
+  @override
+  bool operator ==(Object other) {
+    return other is AndroidWebViewWidgetCreationParams &&
+        controller == other.controller &&
+        layoutDirection == other.layoutDirection &&
+        displayWithHybridComposition == other.displayWithHybridComposition &&
+        platformViewsServiceProxy == other.platformViewsServiceProxy &&
+        instanceManager == other.instanceManager;
+  }
 }
 
 /// An implementation of [PlatformWebViewWidget] with the Android WebView API.
@@ -763,7 +782,9 @@
   @override
   Widget build(BuildContext context) {
     return PlatformViewLink(
-      key: _androidParams.key,
+      // Setting a default key using `params` ensures the `PlatformViewLink`
+      // recreates the PlatformView when changes are made.
+      key: _androidParams.key ?? ObjectKey(params),
       viewType: 'plugins.flutter.io/webview',
       surfaceFactory: (
         BuildContext context,
diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml
index eb79daf..f56b5a6 100644
--- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml
+++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml
@@ -2,7 +2,7 @@
 description: A Flutter plugin that provides a WebView widget on Android.
 repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
-version: 3.9.1
+version: 3.9.2
 
 environment:
   sdk: ">=2.18.0 <4.0.0"
diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart
index a6905c7..f3bdb63 100644
--- a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart
+++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart
@@ -1216,5 +1216,68 @@
         ),
       );
     });
+
+    testWidgets('PlatformView is recreated when the controller changes',
+        (WidgetTester tester) async {
+      final MockPlatformViewsServiceProxy mockPlatformViewsService =
+          MockPlatformViewsServiceProxy();
+
+      when(
+        mockPlatformViewsService.initSurfaceAndroidView(
+          id: anyNamed('id'),
+          viewType: anyNamed('viewType'),
+          layoutDirection: anyNamed('layoutDirection'),
+          creationParams: anyNamed('creationParams'),
+          creationParamsCodec: anyNamed('creationParamsCodec'),
+          onFocus: anyNamed('onFocus'),
+        ),
+      ).thenReturn(MockSurfaceAndroidViewController());
+
+      await tester.pumpWidget(Builder(
+        builder: (BuildContext context) {
+          return AndroidWebViewWidget(
+            AndroidWebViewWidgetCreationParams(
+              controller: createControllerWithMocks(),
+              platformViewsServiceProxy: mockPlatformViewsService,
+            ),
+          ).build(context);
+        },
+      ));
+      await tester.pumpAndSettle();
+
+      verify(
+        mockPlatformViewsService.initSurfaceAndroidView(
+          id: anyNamed('id'),
+          viewType: anyNamed('viewType'),
+          layoutDirection: anyNamed('layoutDirection'),
+          creationParams: anyNamed('creationParams'),
+          creationParamsCodec: anyNamed('creationParamsCodec'),
+          onFocus: anyNamed('onFocus'),
+        ),
+      );
+
+      await tester.pumpWidget(Builder(
+        builder: (BuildContext context) {
+          return AndroidWebViewWidget(
+            AndroidWebViewWidgetCreationParams(
+              controller: createControllerWithMocks(),
+              platformViewsServiceProxy: mockPlatformViewsService,
+            ),
+          ).build(context);
+        },
+      ));
+      await tester.pumpAndSettle();
+
+      verify(
+        mockPlatformViewsService.initSurfaceAndroidView(
+          id: anyNamed('id'),
+          viewType: anyNamed('viewType'),
+          layoutDirection: anyNamed('layoutDirection'),
+          creationParams: anyNamed('creationParams'),
+          creationParamsCodec: anyNamed('creationParamsCodec'),
+          onFocus: anyNamed('onFocus'),
+        ),
+      );
+    });
   });
 }
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
index f214225..35b2b8f 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
+++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 3.7.2
+
+* Fixes bug where `PlatformWebViewWidget` doesn't rebuild when the controller changes.
+
 ## 3.7.1
 
 * Updates pigeon version to `10.1.4`.
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart
index 14cba33..5b87a39 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart
@@ -632,6 +632,21 @@
   // Maintains instances used to communicate with the native objects they
   // represent.
   final InstanceManager _instanceManager;
+
+  @override
+  int get hashCode => Object.hash(
+        controller,
+        layoutDirection,
+        _instanceManager,
+      );
+
+  @override
+  bool operator ==(Object other) {
+    return other is WebKitWebViewWidgetCreationParams &&
+        controller == other.controller &&
+        layoutDirection == other.layoutDirection &&
+        _instanceManager == other._instanceManager;
+  }
 }
 
 /// An implementation of [PlatformWebViewWidget] with the WebKit api.
@@ -651,7 +666,9 @@
   @override
   Widget build(BuildContext context) {
     return UiKitView(
-      key: _webKitParams.key,
+      // Setting a default key using `params` ensures the `UIKitView` recreates
+      // the PlatformView when changes are made.
+      key: _webKitParams.key ?? ObjectKey(params),
       viewType: 'plugins.flutter.io/webview',
       onPlatformViewCreated: (_) {},
       layoutDirection: params.layoutDirection,
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
index f213fbc..6e80a39 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
+++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
@@ -2,7 +2,7 @@
 description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control.
 repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22
-version: 3.7.1
+version: 3.7.2
 
 environment:
   sdk: ">=2.18.0 <4.0.0"
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.dart
index 443e3a7..ae9ab6b 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_widget_test.dart
@@ -24,37 +24,8 @@
         onWeakReferenceRemoved: (_) {},
       );
 
-      final WebKitWebViewController controller = WebKitWebViewController(
-        WebKitWebViewControllerCreationParams(
-          webKitProxy: WebKitProxy(createWebView: (
-            WKWebViewConfiguration configuration, {
-            void Function(
-              String keyPath,
-              NSObject object,
-              Map<NSKeyValueChangeKey, Object?> change,
-            )? observeValue,
-            InstanceManager? instanceManager,
-          }) {
-            final WKWebView webView = WKWebView.detached(
-              instanceManager: testInstanceManager,
-            );
-            testInstanceManager.addDartCreatedInstance(webView);
-            return webView;
-          }, createWebViewConfiguration: ({InstanceManager? instanceManager}) {
-            return MockWKWebViewConfiguration();
-          }, createUIDelegate: ({
-            dynamic onCreateWebView,
-            dynamic requestMediaCapturePermission,
-            InstanceManager? instanceManager,
-          }) {
-            final MockWKUIDelegate mockWKUIDelegate = MockWKUIDelegate();
-            when(mockWKUIDelegate.copy()).thenReturn(MockWKUIDelegate());
-
-            testInstanceManager.addDartCreatedInstance(mockWKUIDelegate);
-            return mockWKUIDelegate;
-          }),
-        ),
-      );
+      final WebKitWebViewController controller =
+          createTestWebViewController(testInstanceManager);
 
       final WebKitWebViewWidget widget = WebKitWebViewWidget(
         WebKitWebViewWidgetCreationParams(
@@ -71,5 +42,86 @@
       expect(find.byType(UiKitView), findsOneWidget);
       expect(find.byKey(const Key('keyValue')), findsOneWidget);
     });
+
+    testWidgets('Key of the PlatformView changes when the controller changes',
+        (WidgetTester tester) async {
+      final InstanceManager testInstanceManager = InstanceManager(
+        onWeakReferenceRemoved: (_) {},
+      );
+
+      // Pump WebViewWidget with first controller.
+      final WebKitWebViewController controller1 =
+          createTestWebViewController(testInstanceManager);
+      final WebKitWebViewWidget webViewWidget = WebKitWebViewWidget(
+        WebKitWebViewWidgetCreationParams(
+          controller: controller1,
+          instanceManager: testInstanceManager,
+        ),
+      );
+
+      await tester.pumpWidget(
+        Builder(
+          builder: (BuildContext context) => webViewWidget.build(context),
+        ),
+      );
+      await tester.pumpAndSettle();
+
+      expect(find.byKey(ObjectKey(webViewWidget.params)), findsOneWidget);
+
+      // Pump WebViewWidget with second controller.
+      final WebKitWebViewController controller2 =
+          createTestWebViewController(testInstanceManager);
+      final WebKitWebViewWidget webViewWidget2 = WebKitWebViewWidget(
+        WebKitWebViewWidgetCreationParams(
+          controller: controller2,
+          instanceManager: testInstanceManager,
+        ),
+      );
+
+      await tester.pumpWidget(
+        Builder(
+          builder: (BuildContext context) => webViewWidget2.build(context),
+        ),
+      );
+      await tester.pumpAndSettle();
+
+      expect(find.byKey(ObjectKey(webViewWidget2.params)), findsOneWidget);
+    });
   });
 }
+
+WebKitWebViewController createTestWebViewController(
+  InstanceManager testInstanceManager,
+) {
+  return WebKitWebViewController(
+    WebKitWebViewControllerCreationParams(
+      webKitProxy: WebKitProxy(createWebView: (
+        WKWebViewConfiguration configuration, {
+        void Function(
+          String keyPath,
+          NSObject object,
+          Map<NSKeyValueChangeKey, Object?> change,
+        )? observeValue,
+        InstanceManager? instanceManager,
+      }) {
+        final WKWebView webView = WKWebView.detached(
+          instanceManager: testInstanceManager,
+        );
+        testInstanceManager.addDartCreatedInstance(webView);
+        return webView;
+      }, createWebViewConfiguration: ({InstanceManager? instanceManager}) {
+        return MockWKWebViewConfiguration();
+      }, createUIDelegate: ({
+        dynamic onCreateWebView,
+        dynamic requestMediaCapturePermission,
+        InstanceManager? instanceManager,
+      }) {
+        final MockWKUIDelegate mockWKUIDelegate = MockWKUIDelegate();
+        when(mockWKUIDelegate.copy()).thenReturn(MockWKUIDelegate());
+
+        testInstanceManager.addDartCreatedInstance(mockWKUIDelegate);
+        return mockWKUIDelegate;
+      }),
+    ),
+  );
+}