回答編集履歴

3

調査し直した内容に修正しました

2019/10/21 10:56

投稿

popobot
popobot

スコア6586

test CHANGED
@@ -1,137 +1,37 @@
1
+ **初期の回答はリビルドしないと勘違いしていたので、調査し直した内容を修正しました...すみません**
2
+
3
+
4
+
5
+ 現時点(Flutter 1.9)では、`Navigator`で`push`や`pop`した際に、`Navigator`にスタックされているページは、リビルドされる仕様のようです。なお、リビルドを抑制するようなオプションは存在しないと思います
6
+
7
+ * `maintainState:false`にすることで、リビルドは抑制できますが、スタックされた遷移前のページは状態が破棄されるので、戻ったタイミングで初期状態でビルドされてます。これはこれでよくないケースがありそう
8
+
9
+ * `StatelessWidget`で構成されているケースでリビルドしない場合もありました(回答履歴参照)
10
+
11
+
12
+
13
+ 詳しくは以下の本家のイシューに書かれています。
14
+
15
+ [https://github.com/flutter/flutter/issues/11655
16
+
17
+ ](https://github.com/flutter/flutter/issues/11655)
18
+
19
+
20
+
21
+ イシューによれば、基本的に`Widget`の`build`は冪等性があり、リビルドされても同じ状態であれば、同じ結果を生成されるので、問題にはならない。ただし、パフォーマンス上よくないケースもあるので、今後何らかの対応があるかもしれないようです。
22
+
23
+
24
+
25
+ 個人的には、特段パフォーマンス上の問題がなければ、リビルドされても気にしなくていい気がします。
26
+
27
+
28
+
29
+ ---
30
+
31
+
32
+
1
33
  > この部分ではFirstPageをリビルドしてoffstageに追加しているのでしょうか?
2
34
 
3
35
 
4
36
 
5
- 記事をベースに簡単なサンプルコードを書いて動かしてみましたが、リビルドはしていないようです
6
-
7
- ※画面遷移しても`rebuild`と出力されない
8
-
9
-
10
-
11
- ```
12
-
13
- import 'package:flutter/material.dart';
14
-
15
-
16
-
17
- void main() => runApp(MyApp());
18
-
19
-
20
-
21
- class MyApp extends StatelessWidget {
22
-
23
- @override
24
-
25
- Widget build(BuildContext context) {
26
-
27
- return MaterialApp(
28
-
29
- title: 'Flutter Demo',
30
-
31
- home: FirstPage(),
32
-
33
- );
34
-
35
- }
36
-
37
- }
38
-
39
-
40
-
41
- class FirstPage extends StatelessWidget {
42
-
43
- @override
44
-
45
- Widget build(BuildContext context) {
46
-
47
- print('rebuild');
48
-
49
- return Scaffold(
50
-
51
- appBar: AppBar(title: Text('FirstPage')),
52
-
53
- body: Center(
54
-
55
- child: RaisedButton(
56
-
57
- child: Text('Next'),
58
-
59
- onPressed: () {
60
-
61
- Navigator.of(context).push(
62
-
63
- MaterialPageRoute(
64
-
65
- builder: (context) {
66
-
67
- return SecondPage();
68
-
69
- },
70
-
71
- ),
72
-
73
- );
74
-
75
- },
76
-
77
- ),
78
-
79
- ),
80
-
81
- );
82
-
83
- }
84
-
85
- }
86
-
87
-
88
-
89
- class SecondPage extends StatelessWidget {
90
-
91
- @override
92
-
93
- Widget build(BuildContext context) {
94
-
95
- return Scaffold(
96
-
97
- appBar: AppBar(title: Text('SecondPage')),
98
-
99
- body: Center(
100
-
101
- child: RaisedButton(
102
-
103
- child: Text('Back'),
104
-
105
- onPressed: () {
106
-
107
- Navigator.of(context).pop();
108
-
109
- },
110
-
111
- ),
112
-
113
- ),
114
-
115
- );
116
-
117
- }
118
-
119
- }
120
-
121
- ```
122
-
123
-
124
-
125
- > 3.アニメーション終了後、StackからFirstPageをoffstageに追加する
126
-
127
-
128
-
129
- 「StackからFirstPageをoffstage移動す」とい表現の方が適切なのかもしれません(あまり自信ないですが)
37
+ 厳密にはリビルドして追加しているのではなく、Navigatorのスタック変化があった場合に、リビルドが実行されうです
130
-
131
-
132
-
133
- `Flutter Inspector`の`Render Tree`をみると、`Overlay`内部の`_RenderTheatre`で`Stack`と`Offstage`に分かれており、FirstPageは遷移前は`Stack`配下にいましたが、遷移後は`Offstage`配下にいました。より厳密にはソースコードを読めばわかるのかもですが難しい...
134
-
135
-
136
-
137
- ※記事を書いた方にも聞いてみるといいかもしれませんね

2

補足

2019/10/21 10:56

投稿

popobot
popobot

スコア6586

test CHANGED
@@ -130,7 +130,7 @@
130
130
 
131
131
 
132
132
 
133
- `Flutter Inspector`の`Render Tree`をみると、`Stack`と`Offstage`に分かれており、FirstPageは遷移前は`Stack`配下にいましたが、遷移後は`Offstage`配下にいました。より厳密にはソースコードを読めばわかるのかもです
133
+ `Flutter Inspector`の`Render Tree`をみると、`Overlay`内部の`_RenderTheatre`で`Stack`と`Offstage`に分かれており、FirstPageは遷移前は`Stack`配下にいましたが、遷移後は`Offstage`配下にいました。より厳密にはソースコードを読めばわかるのかもですが難しい...
134
134
 
135
135
 
136
136
 

1

補足

2019/10/20 21:59

投稿

popobot
popobot

スコア6586

test CHANGED
@@ -134,4 +134,4 @@
134
134
 
135
135
 
136
136
 
137
- 記事を書いた方にも聞いてみるといいかもしれませんね
137
+ 記事を書いた方にも聞いてみるといいかもしれませんね