Flutter開発実践 - ValueListenableBuilderで部分リフレッシュ機能を実装
作成された新しいプロジェクトでは、ボタンをクリックしてカウンターを更新した後、setState を通じてこのクラスのビルド メソッドを開始して更新できます。コントロールのごく一部のみを更新する必要がある場合、setState を使用するのは適切ではなく、プロバイダーなどの状態管理ライブラリを使用して部分的な更新が必要になります。もちろん、フラッターはローカル コントロールを更新するための ValueListenableBuilder を提供します。
一、ValueListenableBuilder
ValueListenableBuilderのプロパティは次のとおりです。
const ValueListenableBuilder({
super.key,
required this.valueListenable,
required this.builder,
this.child,
}) : assert(valueListenable != null),
assert(builder != null);
- ValueListenable は Listenable を継承し、リッスン可能なオブジェクトです。
- ビルダーは 1 つの typedef
typedef ValueWidgetBuilder = Widget Function(BuildContext context, T value, Widget? child); - 子、オプション、空にすることもできます
ValueListenableBuilder クラスの実装を見ると、次のことがわかります。
class _ValueListenableBuilderState<T> extends State<ValueListenableBuilder<T>> {
late T value;
@override
void initState() {
super.initState();
value = widget.valueListenable.value;
widget.valueListenable.addListener(_valueChanged);
}
@override
void didUpdateWidget(ValueListenableBuilder<T> oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.valueListenable != widget.valueListenable) {
oldWidget.valueListenable.removeListener(_valueChanged);
value = widget.valueListenable.value;
widget.valueListenable.addListener(_valueChanged);
}
}
@override
void dispose() {
widget.valueListenable.removeListener(_valueChanged);
super.dispose();
}
void _valueChanged() {
setState(() { value = widget.valueListenable.value; });
}
@override
Widget build(BuildContext context) {
return widget.builder(context, value, widget.child);
}
}
initState では、受信する listenable オブジェクトを監視し、_valueChanged メソッドを実行します。_valueChanged は setState を実行して、現在の状態の更新をトリガーします。 setState が build メソッドを実行し、build メソッドの実行をトリガーし、最後に widget.builder コールバックをトリガーすることで、部分的な更新が行われることがわかっています。
子の役割も非常に重要で、子の中にウィジェットを入れておきますが、ビルダーを実行する際には子が直接使用され、再度ビルドされることはありません。
2. ValueListenableBuilderによる部分リフレッシュの例
以下では、ValueListenableBuilder を使用して部分更新の例を実装しています。この例では、インターフェイスに、isShowNotifier の値の変更を制御するための表示ボタンと非表示ボタンがあります。 ValueListenableBuilder のビルダーを通じて表示する必要があるコンテンツを決定します。
サンプルコードは次のとおりです
import 'package:flutter/material.dart';
class ValueListenablePage extends StatefulWidget {
const ValueListenablePage({super.key});
@override
State<ValueListenablePage> createState() => _ValueListenablePageState();
}
class _ValueListenablePageState extends State<ValueListenablePage> {
final isShowNotifier = ValueNotifier<bool>(false);
@override
void initState() {
// TODO: implement initState
super.initState();
}
void show() {
isShowNotifier.value = true;
}
void hide() {
isShowNotifier.value = false;
}
@override
void dispose() {
// TODO: implement dispose
isShowNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
title: const Text('ValueListenablePage'),
),
body: Container(
width: screenSize.width,
height: screenSize.height,
child: Stack(
alignment: Alignment.center,
children: [
Positioned(
top: 50,
child: buildValueListenable(context),
),
Positioned(
top: 200,
child: buildButton(context),
),
],
),
),
);
}
Widget buildHide(BuildContext context) {
return Container(
color: Colors.green,
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 50),
child: Text(
"当前隐藏",
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.italic,
color: Colors.white,
decoration: TextDecoration.none,
),
),
);
}
Widget buildValueListenable(BuildContext context) {
return ValueListenableBuilder(
valueListenable: isShowNotifier,
builder: (BuildContext aContext, bool isShow, Widget? child) {
if (isShow) {
return child ?? buildHide(context);
} else {
return buildHide(context);
}
},
child: Container(
color: Colors.blueGrey,
padding: EdgeInsets.symmetric(vertical: 50, horizontal: 50),
child: Text(
"ValueListenableBuilder Child",
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
softWrap: true,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
fontStyle: FontStyle.italic,
color: Colors.white,
decoration: TextDecoration.none,
),
),
),
);
}
Widget buildButton(BuildContext context) {
return Container(
width: 300,
height: 220,
color: Colors.deepOrange,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextButton(
onPressed: () {
show();
},
child: Container(
height: 50,
width: 200,
color: Colors.lightBlue,
alignment: Alignment.center,
child: Text(
'点击显示',
style: TextStyle(
fontSize: 14,
color: Colors.white,
),
),
),
),
TextButton(
onPressed: () {
hide();
},
child: Container(
height: 50,
width: 200,
color: Colors.lightBlue,
alignment: Alignment.center,
child: Text(
'点击隐藏',
style: TextStyle(
fontSize: 14,
color: Colors.white,
),
),
),
),
],
),
);
}
}
レンダリングは次のとおりです
3. まとめ
Flutter開発実践 - ValueListenableBuilderで部分リフレッシュ機能を実装
勉強して記録し、日々改善を続けてください。