ビルド方法は、それがあるべきように設計された副作用なし/ピュア。これは、次のような多くの外部要因が新しいウィジェットのビルドをトリガーする可能性があるためです。
- ルートポップ/プッシュ
- 画面のサイズ変更、通常はキーボードの外観または向きの変更による
- 親ウィジェットが子を再作成しました
- ウィジェットが依存するInheritedWidget(
Class.of(context)
パターン)の変更
この手段build
方法はすべきではない HTTP呼び出しをトリガーするか、いずれかの状態を変更します。
これは質問とどのように関連していますか?
あなたが直面している問題は、あなたのビルドメソッドに副作用がある/純粋ではないため、無関係なビルド呼び出しが面倒になることです。
ビルド呼び出しを防止する代わりに、ビルドメソッドを純粋にして、影響なくいつでも呼び出せるようにする必要があります。
あなたの例の場合、ウィジェットをに変換し、StatefulWidget
そのHTTP呼び出しをのに抽出しinitState
ますState
:
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
Future<int> future;
@override
void initState() {
future = Future.value(42);
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: future,
builder: (context, snapshot) {
// create some layout here
},
);
}
}
私はすでにこれを知っています。私はので、私はここに来たのは本当に最適化再構築したいです
また、子にビルドを強制することなく、ウィジェットを再ビルドできるようにすることもできます。
ウィジェットのインスタンスが同じままの場合。Flutterは意図的に子供を再建しません。これは、不要な再構築を防ぐためにウィジェットツリーの一部をキャッシュできることを意味します。
最も簡単な方法は、dart const
コンストラクターを使用することです。
@override
Widget build(BuildContext context) {
return const DecoratedBox(
decoration: BoxDecoration(),
child: Text("Hello World"),
);
}
そのconst
キーワードのおかげDecoratedBox
で、ビルドが数百回呼び出されても、のインスタンスは同じままです。
ただし、手動で同じ結果を得ることができます。
@override
Widget build(BuildContext context) {
final subtree = MyWidget(
child: Text("Hello World")
);
return StreamBuilder<String>(
stream: stream,
initialData: "Foo",
builder: (context, snapshot) {
return Column(
children: <Widget>[
Text(snapshot.data),
subtree,
],
);
},
);
}
この例では、StreamBuilderに新しい値が通知されたsubtree
場合、StreamBuilder / Column が通知しても再構築しません。これは、閉鎖のおかげでのインスタンスがMyWidget
変更されなかったために発生します。
このパターンはアニメーションでよく使用されます。典型的な用途はAnimatedBuilder
、などのすべての遷移AlignTransition
です。
subtree
クラスのフィールドに格納することもできますが、ホットリロード機能が無効になるためお勧めしません。