今回の問題
ある日のこと、
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をしたのがきっかけです。
コードで書くと↓みたいな感じです。
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とかって勝手にされると怖いです。
まぁいつビルドされても問題ないようにコーディングするべきだとは思いますが……
という感想です。