Provider/Consumerを利用した学習コードの作成
- ChangeNotifierを実装したCartModelを作成。
- ChangeNotifierのメソッド一覧を見ると、addListenr,removeListener,notifyListenersが羅列されている。Javaで言うところのEvent Listenerのようなものとなんとなく理解。
- 状態管理するモデルのデータを反映したいツリーの1つ上の階層で、Providerとして登録(設定)すると、配下のツリーにデータ更新時のイベントが通知される仕組みのようだ。
- 状態更新を受け取る側(Widget)をConsumerで囲ってあげることで、対象のWidgetで通知を受け取ることができる。
- Consumerは上位ツリーで受け取ることもできるが、Widgetのrebuildにも影響があるため、また更新が必要なWidgetに範囲を狭めた方が可読性もあり良いとのこと。
「shuffle」ボタンを押下する度に表示データが再描画されるコード
なんとなくの感覚で書いたので、より詳しく調べて学んでいく必要がある。listenをtrueにすると実行時エラーが発生する。ドキュメントをろくに読んでいないので、通知を受け取るとループするとかそんな感じなのか。
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CartModel with ChangeNotifier {
List<int> values = [1, 2, 3, 4, 5];
void shuffle() {
values.shuffle();
print(values); //デバッグ用
notifyListeners();//通知発火
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
//Providerの登録
//Provider1つの登録なのでMutiProviderを使う必要はないが、書きやすかったのでこちらを利用。
return MultiProvider(
providers: [
ChangeNotifierProvider<CartModel>(
create: (context) => CartModel(),
),
],
child: const MaterialApp(
home: Home(),
),
);
}
}
class Home extends StatelessWidget {
const Home({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//CartModelの値が更新されたらRow内の再描画を行いたいので、ここでConsumerを設定
Consumer<CartModel>(
builder: (context, CartModel model, child) => Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//CartModelに保存された数字を順番にTextオブジェクト化
...List.generate(
model.values.length,
(int index) => Text(model.values[index].toString()),
),
],
),
),
ElevatedButton(
child: const Text('shuffle'),
onPressed: () => {
//登録されたProviderのうちCartModel型のものを取り出し、shuffleメソッドを実行。
Provider.of<CartModel>(context, listen: false).shuffle(),
},
)
],
),
),
);
}
}