Repository: flutter
Issue: `DialogRoute` doesn't rebuild unless the key changes.
Labels: framework,f: routes,has reproducible steps,P2,found in release: 3.3,found in release: 3.6,team-framework,triaged-framework

## Steps to Reproduce


1. Execute `flutter run` on the code sample (see "Code sample" section below) 
2. Click on "Dialog" button to display the dialog
3. Try to go to the dialog on the right
4. Notice that the dialog doesn't change

**Expected results:** <!-- what did you want to see? -->

I'm expecting the dialog to rebuild

**Actual results:** <!-- what did you see? -->

It is not rebuilding.
I can force it to rebuild by changing the key `ValueKey('dialog-$_selected'),` instead of `ValueKey('dialog'),`
But doing so prevents me from reusing states.

You can see in the logs that it goes through the `initState` of `_DialogWidgetState`:

```
flutter: initState 1
flutter: initState 2
flutter: initState 3
flutter: initState 2
flutter: initState 1
```

I believe this might be coming from 

https://github.com/flutter/flutter/blob/de4c0b19a2604e2cdf8e662b8e0b0ee28fc66ba1/packages/flutter/lib/src/widgets/routes.dart#L1710-L1717

and/or

https://github.com/flutter/flutter/blob/de4c0b19a2604e2cdf8e662b8e0b0ee28fc66ba1/packages/flutter/lib/src/widgets/routes.dart#L817-L821

As a comparison, I also included another example with the `MaterialPage` which works fine.

<details>
<summary>Code sample</summary>

Or you can check out https://github.com/ValentinVignal/flutter_app_stable/tree/flutter/dialog-being-cached

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class AppRoute {
  const AppRoute(this.location);
  final int? location;
}

class AppRouter extends RouterDelegate<AppRoute>
    with PopNavigatorRouterDelegateMixin, ChangeNotifier {
  // get correct state of router
  @override
  AppRoute get currentConfiguration => AppRoute(_selected);

  int? _selected;
  int get selected => _selected!;
  set selected(int value) {
    _selected = value == 0 ? null : value;
    notifyListeners();
  }

  @override
  Widget build(BuildContext context) {
    return Navigator(
      key: _navigatorKey,
      onPopPage: (route, result) {
        if (!route.didPop(result)) {
          return false;
        }
        _selected = null;
        notifyListeners();
        return true;
      },
      pages: [
        const MaterialPage(
          key: ValueKey('home'),
          child: Home(),
        ),
        if (_selected != null && _selected! > 0)
          DialogPage(
            key: const ValueKey('dialog'),  // <- Replace with `ValueKey('dialog-$selected')`, and the UI rebuilds but the state of the dialog is lost. It will print `'iniState1'`, `'iniState2'`... in `_DialogWidgetState`'s `initState`.
            child: DialogWidget(
              parameter: _selected!,
            ),
          )
        else if (_selected != null && _selected! < 0)
          MaterialPage(
            key: const ValueKey('material'),
            child: DialogWidget(
              parameter: _selected!,
            ),
          )
      ],
    );
  }

  final _navigatorKey = GlobalKey<NavigatorState>();
  @override
  GlobalKey<NavigatorState> get navigatorKey => _navigatorKey;

  @override
  Future<void> setNewRoutePath(AppRoute configuration) async {
    _selected = configuration.location;
  }
}

class AppRouteInformationParser extends RouteInformationParser<AppRoute> {
  // This converts route state to route information.
  @override
  RouteInformation restoreRouteInformation(configuration) {
    final String location;
    if (configuration.location == null) {
      location = '/';
    } else {
      location = '/dialog/${configuration.location}';
    }
    return RouteInformation(location: location);
  }

// This converts route info to router state
  @override
  Future<AppRoute> parseRouteInformation(
      RouteInformation routeInformation) async {
    final int? selected;
    if (routeInformation.location?.startsWith('/dialog/') ?? false) {
      selected = int.parse(routeInformation.location!.split('/').last);
    } else {
      selected = null;
    }
    return AppRoute(selected);
  }
}

final delegate = AppRouter();
final informationParser = AppRouteInformationParser();

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: delegate,
      routeInformationParser: informationParser,
    );
  }
}

class Home extends StatelessWidget {
  const Home({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ElevatedButton(
              onPressed: () {
                delegate.selected = 1;
              },
              child: const Text('Dialog'),
            ),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: () {
                delegate.selected = -1;
              },
              child: const Text('Material'),
            ),
          ],
        ),
      ),
    );
  }
}

class DialogWidget extends StatefulWidget {
  const DialogWidget({
    required this.parameter,
    super.key,
  });

  final int parameter;

  @override
  State<DialogWidget> createState() => _DialogWidgetState();
}

class _DialogWidgetState extends State<DialogWidget> {
  @override
  void initState() {
    super.initState();
    print('initState ${widget.parameter}');
  }

  @override
  Widget build(BuildContext context) {
    return SimpleDialog(
      title: const Text('Dialog'),
      children: [
        Row(
          children: [
            IconButton(
              onPressed: () {
                delegate.selected--;
              },
              icon: const Icon(Icons.arrow_back_ios),
            ),
            Text(widget.parameter.toString()),
            IconButton(
              onPressed: () {
                delegate.selected++;
              },
              icon: const Icon(Icons.arrow_forward_ios),
            ),
          ],
        ),
      ],
    );
  }
}

class DialogPage extends Page {
  const DialogPage({
    required this.child,
    super.key,
  });

  final Widget child;

  @override
  Route createRoute(BuildContext context) {
    return _DialogRoute(
      settings: this,
      context: context,
      builder: (context) {
        ModalRoute.of(context);
        return child;
      },
    );
  }
}

class _DialogRoute extends DialogRoute {
  _DialogRoute({
    super.settings,
    required super.context,
    required super.builder,
  });

  @override
  bool canTransitionFrom(TransitionRoute previousRoute) {
    return previousRoute is! _DialogRoute;
  }

  @override
  bool canTransitionTo(TransitionRoute nextRoute) {
    return nextRoute is! _DialogRoute;
  }
}
```

</details>

<details>
  <summary>Logs</summary>


For the logs, see the table in the _"Videos"_ section.

```
Analyzing flutter_app_stable...                                         

   info • Avoid `print` calls in production code • lib/main.dart:158:5 • avoid_print

1 issue found. (ran in 5.0s)
```

<!-- Finally, paste the output of running `flutter doctor -v` here. -->

```
[✓] Flutter (Channel stable, 3.3.8, on macOS 11.6.8 20G730 darwin-x64, locale en-GB)
    • Flutter version 3.3.8 on channel stable at /Users/valentin/flutter/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 52b3dc25f6 (9 days ago), 2022-11-09 12:09:26 +0800
    • Engine revision 857bd6b74c
    • Dart version 2.18.4
    • DevTools version 2.15.0

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /usr/local/Caskroom/android-sdk/4333796
    • Platform android-33, build-tools 30.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 13C100
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)

[✓] VS Code (version 1.73.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.52.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-x64     • macOS 11.6.8 20G730 darwin-x64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 107.0.5304.110

[✓] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!
```

</details>


<details>
  <Summary>Videos</Summary>


<table>
  <tr>
    <th>
    </th>
    <th>
      With `const ValueKey('dialog')` as a key
    </th>
     <th>
       With `ValueKey('dialog-$_selected')` as a key
      </th>
  </tr>
  <tr>
    <td>
      Video
     </td>
     <td>
      <video src="https://user-images.githubusercontent.com/32538273/202673566-0cee1655-02a8-45f4-8773-b1df5fe3312e.mov"/>
    </td>
    <td>
      <video src="https://user-images.githubusercontent.com/32538273/202675559-88923bef-fe36-43d3-be81-22c75433faef.mov" />
    </td>
  </tr>
  <tr>
    <td>
      Logs
    </td>
    <td>

```zsh
flutter run -d macos
Launching lib/main.dart on macOS in debug mode...
Building macOS application...                                           
Syncing files to device macOS...                                    71ms

Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).

💪 Running with sound null safety 💪

An Observatory debugger and profiler on macOS is available at: http://127.0.0.1:62454/Sc8VIzL_xkw=/
The Flutter DevTools debugger and profiler on macOS is available at:
http://127.0.0.1:9102?uri=http://127.0.0.1:62454/Sc8VIzL_xkw=/
flutter: initState -1
flutter: initState -1
flutter: initState 1
```

</td>
<td>

```zsh
Launching lib/main.dart on macOS in debug mode...
Building macOS application...                                           
Syncing files to device macOS...                                    71ms

Flutter run key commands.
r Hot reload. 🔥🔥🔥
R Hot restart.
h List all available interactive commands.
d Detach (terminate "flutter run" but leave application running).
c Clear the screen
q Quit (terminate the application on the device).

💪 Running with sound null safety 💪

An Observatory debugger and profiler on macOS is available at: http://127.0.0.1:63181/P2tBIa5DOV8=/
The Flutter DevTools debugger and profiler on macOS is available at:
http://127.0.0.1:9102?uri=http://127.0.0.1:63181/P2tBIa5DOV8=/
flutter: initState -1
flutter: initState 1
flutter: initState 2
flutter: initState 3
flutter: initState 2
flutter: initState 1
```

</td>
</tr>
</table>


</details>