flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
166.14k stars 27.47k forks source link

Hot reload doesn't work on Dialogs and BottomSheets #18709

Closed escamoteur closed 5 years ago

escamoteur commented 6 years ago

While designing a dialog yesterday I had to find out that how reload doesn't work on an open Dialog or Bottomsheet.

You can see this in this screencast https://www.screencast.com/t/AmcXBEs7xaj

The App is just the automatically created one by flutter new

@override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return new Scaffold(
      appBar: new AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: new Text(widget.title),
      ),

      floatingActionButton: new FloatingActionButton(
        onPressed: () async => await showMessageDialog(context, "title", "message"),
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Future showMessageDialog(BuildContext context, String title, String message,
    [String buttonText = 'OK']) async {
  await showDialog<Null>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return new AlertDialog(
          title: new Text(title),
          content: Text(message),
          actions: <Widget>[
            new FlatButton(
              child: new Text('CANCEL'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      });
}
PS C:\Entwicklung\FlutterApps\Tests\dialog_hot_reload_repro> flutter doctor -v
[√] Flutter (Channel master, v0.5.6-pre.29, on Microsoft Windows [Version 10.0.17134.112], locale de-DE)
    • Flutter version 0.5.6-pre.29 at C:\Entwicklung\Flutter
    • Framework revision b78f8cdcae (3 days ago), 2018-06-19 18:38:21 +0200
    • Engine revision 0c119932c0
    • Dart version 2.0.0-dev.62.0.flutter-4b2d60cb18

[√] Android toolchain - develop for Android devices (Android SDK 27.0.3)
    • Android SDK at C:\Users\escam\AppData\Local\Android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-27, build-tools 27.0.3
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b02)
    • All Android licenses accepted.

[√] Android Studio (version 3.1)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 24.2.1
    • Dart plugin version 173.4700
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b02)

[√] VS Code, 32-bit edition (version 1.24.1)
    • VS Code at C:\Program Files (x86)\Microsoft VS Code
    • Flutter extension version 2.14.0

[√] Connected devices (1 available)
    • Android SDK built for x86 • emulator-5554 • android-x86 • Android 7.1.1 (API 25) (emulator)

• No issues found!

Thanks and keep going with your awesome work!
escamoteur commented 6 years ago

Thanks to https://github.com/flutter/flutter/issues/13831#issuecomment-354894994

I was able to find a workaround. Creating you own widget ensures that its build method will be called on an hot reload:

Future showMessageDialog(BuildContext context, String title, String message,
    [String buttonText = 'OK']) async {
  await showDialog<Null>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return new DialogTestWidget(title: title, message: message,);
      });
}

class DialogTestWidget extends StatelessWidget {
  final String title;
  final String message;

  const DialogTestWidget({
    Key key, this.title, this.message,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
              child: new AlertDialog(
        title: new Text(title),
        content: Text(message),
        actions: <Widget>[
          new FlatButton(
            child: new Text('CANCEL'),
            onPressed: () {
              Navigator.of(context).pop();
            },
          ),
        ],
      ),
    );
  }
}

Still the question remain for me if the 'builder' of `showDialog' shouldn't be run on an hot reload because it will confuse a lot of people

zoechi commented 6 years ago

Great! I'm closing this issue then for the reason given in https://github.com/flutter/flutter/issues/13831#issuecomment-354894994

escamoteur commented 6 years ago

@zoechi Please reopen it so that the team has chance to reevaluate the question if this could be improved.

zoechi commented 6 years ago

@escamoteur OK I leave it to the Flutter team, but #13831 was just closed this year, so I wouldn't expect too much.

slightfoot commented 6 years ago

This doesn't exactly link to your problem. But I think a lot of developers don't realise that the State class has a method called reassemble which resolves this kind of issue.

Docs: During development, if a hot reload occurs (whether initiated from the command line flutter tool by pressing r, or from an IDE), the reassemble method is called. This provides an opportunity to reinitialize any data that was prepared in the initState method.

github-actions[bot] commented 3 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.