chatGPT に立ててもらったスケジュールに準じてFlutterの状態管理を勉強。
- Day 5: Flutterの状態管理
- 状態管理の必要性とFlutterの提供する方法を学ぶ
- 状態の共有と更新の方法を理解する
状態管理とは
- なんらかのきっかけから、UIが変わるために「状態管理」する必要がある。
- たとえばユーザーがログインすれば、ログインユーザーのみの画面に遷移するとか、ECアプリでアイテムを追加したらカートの中身が反映されるとか。
- 3つの方法で状態管理ができる
- setState
- リビルド(画面全体の更新)が必要になる⇒重くなる可能性が増える
- Provider
- リビルドせずピンポイントの更新が可能
- 公式に推奨されてる
- Riverpod
- Providerの改良版らしい
- リビルドせずピンポイントの更新が可能
- Flutter に依存しない(pure dart)⇒学習コストが高くなることもある
- setState
状態の共有と更新の方法
学習コスト高すぎると挫折しそうなので以下はProviderにしました。
pubspec.yaml にproviderを導入することを記載
dependencies:
provider: ^6.0.2
ターミナルで依存関係として追加
$ flutter pub add provider
Providerを実装
chatGPTにもらったサンプルソースに分からなかったところをコメントで追加
サンプルソース
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
ChangeNotifierProvider( // ChangeNotifierを使いたいウィジェットを子にする。ChangeNotifierのインスタンスを提供する。
create: (context) => CounterProvider(),
child: MyApp(),
),
);
}
class CounterProvider extends ChangeNotifier { // ChangeNotifier は変更の監視を可能にさせるクラス
int _counter = 0;
int get counter => _counter;
void incrementCounter() {
_counter++;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Counter App with Provider'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Consumer<CounterProvider>( // Consumer<任意のModel> : 提供されたモデルを使うためのWidget Consumerで囲われた部分が更新対象
builder: (context, counterProvider, child) { // (context, ChangeNotifierのインスタンス, child)
return Text('Count: ${counterProvider.counter}');
},
),
ElevatedButton(
onPressed: () {
Provider.of<CounterProvider>(context, listen: false) // <任意のModel>にアクセス メソッドのみ呼び出したいときはlistenをfalseにすると再構築されない 試しにtrueにしてみたら画面上の数は更新されなかった
.incrementCounter();
},
child: Text('Increment'),
),
],
),
),
),
);
}
}
参考
公式ドキュメント
provider
Riverpod
Zenn