LoginSignup
17
11

More than 3 years have passed since last update.

PushしてもStackがあると前画面がReBuildされる問題

Last updated at Posted at 2019-11-29

今回の問題

ある日のこと、
Navigator.pushNamed(context,route)
で気持ちよく遷移してたところ、なぜか前画面のbuildが走ることに気づいた!
なぜ気づいたかは後ほど話します。

どうやらFlutterでは、Stackされてる画面については全てrebuildされるらしい。
↓記事参照
https://github.com/flutter/flutter/issues/11655

これって普通なんでしょうか?
rebuildされても大丈夫なようにコーディングしていけばいい話ではあるんですが、、、
※詳しい方いたら教えてください。

なぜ気づいたのか

FirstView

↓任意のタイミングでダイアログを表示

Dialog

↓OKならSecondViewへpushする

SecondView

みたいな遷移を実装していて、
DialogのOKを押した時に 前画面に戻りたくなかったので
Navigator.pushReplacementNamed(context,'/second')
みたいな感じで消そうとしたんですが、AppBarのLeadingに戻るボタンが付与されて
戻れる状態になっていたので、なんでだろうと思って好奇心で前画面のbuild直下に
printをしたのがきっかけです。

コードで書くと↓みたいな感じです。

main.dart
class FirstView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("firstViewBuild")
    return Scaffold(
        body: Center(
          child: FlatButton(
                onPressed: () {
                  errorDialog(context);
                },
                child: Text("Start"),
              )
        )
    );
  }
}

class SecondView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("secondViewBuild")
    return Scaffold(
        body: Center(
          ///省略
        )
    );
  }
}

void errorDialog(context) {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (_) {
        return AlertDialog(
          title: Text("Warning!!!!"),
          content: Text("ダイアログです"),
          actions: <Widget>[
            FlatButton(
              child: Text(
                  "Cancel",
                  style: TextStyle(
                      color: Colors.black54
                  )
              ),
              onPressed: () {
                Navigator.pop(context);
              },
            ),
            FlatButton(
              child: Text(
                  "OK",
                  style: TextStyle(
                      color: Colors.black54
                  )
              ),
              onPressed: (){
                Navigator.pushReplacementNamed(context, '/second');
              } ,
            ),
          ],
        );
      },
    );
  }

これでダイアログから遷移した時にこうなりました。

I/flutter (15474): secondViewBuild
I/flutter (15474): firstViewBuild

なんでPushしてるのに前画面もBuildされてるねん!!!!
となりました。

解決策

StackされてるのがBuidされてしまうなら消すしかない!とおもったので
なんとか消す方法を考えたところ、
Navigator.pushNamedAndRemoveUntil(context, nextRoute, removeUntilRoute);
がありました!(なんだかんだできるのはFlutterいいですね)

↓公式ページ
https://api.flutter.dev/flutter/widgets/NavigatorState/pushNamedAndRemoveUntil.html

今回は

Navigator.pushNamedAndRemoveUntil(context, '/second', ModalRoute.withName('/'));

これをダイアログのOKのイベントに差し込むことで、FirstViewのStackを消すことに成功しました。

ダイアログからの遷移って結構あるあるなので、できてよかったです。

最後に

結構前画面のBuildとかって勝手にされると怖いです。
まぁいつビルドされても問題ないようにコーディングするべきだとは思いますが……

という感想です。

17
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
11