FlutterはGoogleによって開発されました。
「Widget of the Week」は開発者にFlutterをよく知ってもらうためにGoogleが作った動画で、それぞれのwidgetが持つ特徴をわかりやすく解説しています。
この記事ではWidget of the Weekを日本語で要約しています。
その他、サンプルコードや関連記事もまとめています。
今回は #30 ValueListenableBuilderについてです。
動画
要約
- 1つの値をアプリの各所から参照している場合、値に変更があると複数箇所で再ビルドしなければならず、とても大変
- そんなときはValueListenableBuilderを使おう
- 値が変更された場合、ValueListenableBuilderにその変更が通知され、自動で再ビルドしてくれる
内容
アプリの様々な場所から参照されている特定の値があったとしましょう。
その値が変更されるたび、複数箇所で手動でUIを更新するのはひどく面倒です。
そんなときは、ValueNotifierとValueListenableBuilderを使いましょう。
まず例として、特定の1つの値がいろいろなwidgetから参照されているWidgetツリーがあるとしましょう。
この例をもとに使い方を説明します。

まず、ValueNotifierを用意する必要があります。
例えば 文字列や整数のような 簡単な型の値であれば、ValueNotifier にラップするだけで用意できます。
final value = ValueNotifier(0);
次にこのvalueをValueListenableBuilder内で使います。

ValueListenableBuilderはValueNotifierの値が変わるとその通知を受け、自動的に再構築します。
補足:動画の例だと少しわかりにくいので、別途サンプルコードを記載します。後半でコードの説明をしています。
引用:How to set state from another widget?
class MyHomePage extends StatelessWidget {
final number = new ValueNotifier(0);
@override
Widget build(BuildContext context) {
return Scaffold(
body: ValueListenableBuilder<int>(
valueListenable: number,
builder: (context, value, child) {
return Center(
child: RaisedButton(
onPressed: () {
number.value++;
},
child: MyWidget(number),
),
);
},
),
);
}
}
class MyWidget extends StatelessWidget {
final ValueListenable<int> number;
MyWidget(this.number);
@override
Widget build(BuildContext context) {
return new Text(number.value.toString());
}
}
numberという初期値が0のValueNotifierを作成して、valueListenableに指定しています。
number.value++で値を変更するたび、ValueListenableBuilderのbuildが再実行されます。
ここで注目すべきポイントは、setStateによる明示的な再構築をしていないということです。
ValueListenableBuilderがValueNotifierから変更の通知を受け、自動的に再構築を実施しています。
==補足ここまで==
数値や文字列より複雑なデータの場合はValueNotifierをextendsして専用のValueNotifierを作りましょう。

notifyListeners()により、ValueListenableBuilderに変更を通知することができます。
あなたは自分で作った値変更用の関数の中でnotifyListeners()を実行し、その関数を外から実行することで、値の変更と通知を行うことが可能になります。
ValueListenableBuilderはアニメーションとも相性が良いです。
下の例のようにアニメーションを実現することが可能です。

最後に、ValueListenableBuilderやValueNotifierはInheritedWidgetと組み合せて使うと良いでしょう。
InheritedWidgetを利用して、widgetツリーのどこからでも参照できるValueNotifierのvalueを作ると効果的です。

値が変更された際、各widgetはValueListenableBuilderにより自動的に再ビルドされる。
関連記事
◆ 他のwidgetからsetStateを呼ぶにはどうしたらいい?
How to set state from another widget? – Stack Overflow
質問:
他のwidgetからsetStateを呼ぶにはどうしたらいい?
ベストアンサー:
そもそも他のwidgetからsetStateを呼ぶのは避けるべきです。
widgetが互いに依存し保守性が悪くなるからです。
このような場合はValueListenableBuilderを使ってシンプルに書きましょう。
リンク先にサンプルコードの説明あり。
◆ ValueListenableProviderの日本語での説明記事(似たようなことができるProvider)
[Flutter] package:provider の各プロバイダの詳細 – Qiita
◆ ValueListenableBuilderの利用例
https://twitter.com/_mono/status/1120506905951186945
まとめ
Widget of the Weekの#30 ValueListenableBuilderの日本語翻訳版でした。
ValueListenableBuilderを使うと、開発者は値が変更された後の反映処理に頭を悩ませる必要がなくなり、状態の管理はとてもシンプルになります。
■ 次の記事はこちら
#31 – Draggable
■Widget of the Week まとめ
Widget of the Week 一覧