Provider:Modelを共有する
CoddyのFlutterジャーニー「状態管理」セクションの一部。レッスン 9/27。
ウィジェット同士が近くにある場合は、状態を上位に持ち上げる方法が有効です。アプリ全体のあちこち、たとえば2つの画面、トップバー、リストの奥深くで値が必要になると、その間にあるすべてのウィジェットを通して値を渡すことになります。Providerを使えば、その手間を省けます。これはパッケージです。import 'package:provider/provider.dart';でインポートするコードの集まりです。
これには3つの要素があります。まずモデルです。データを保持し、extends ChangeNotifierを持つクラスです。そのメソッドでデータを変更し、その後notifyListeners()を呼び出します。
class CupCounter extends ChangeNotifier {
int _cups = 0;
int get cups => _cups;
void addCup() {
_cups++;
notifyListeners();
}
}次に、ツリーの上位に置かれたChangeNotifierProviderがモデルを一度作成し、その下にあるすべてのウィジェットに渡します。
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => CupCounter(),
child: const MyApp(),
),
);
}最後に、その下にある任意のウィジェットからモデルを取得します。表示するにはcontext.watch<CupCounter>()を、メソッドを呼び出すにはcontext.read<CupCounter>()を使います。下にあるタイトルとボタンは同じカウンターを取得し、どちらにも何かを渡す必要はありません。
チャレンジ
中級アプリを開くとエラーが表示されます。タイトルが CupCounter を要求しているのに、それより上の部分で何も提供していないためです。
mainで、CupCounterを作成するChangeNotifierProviderでMyAppをラップします。
自分で試してみよう
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CupCounter extends ChangeNotifier {
int _cups = 0;
int get cups => _cups;
void addCup() {
_cups++;
notifyListeners();
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const CupsTitle()),
body: const Center(child: AddCupButton()),
);
}
}
class CupsTitle extends StatelessWidget {
const CupsTitle({super.key});
@override
Widget build(BuildContext context) {
final counter = context.watch<CupCounter>();
return Text('Cups: ${counter.cups}');
}
}
class AddCupButton extends StatelessWidget {
const AddCupButton({super.key});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
context.read<CupCounter>().addCup();
},
child: const Text('Another cup'),
);
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
状態管理のすべてのレッスン
3Provider
Provider:Modelを共有するnotifyListenersを呼び出すProvider:WatchとReadProvider:Consumer2つの画面、1つのModelModel内のオブジェクトのリスト複数のModel:MultiProvider自分で練習してみよう: Flutterオンラインコンパイラ