複数のModel:MultiProvider
CoddyのFlutterジャーニー「状態管理」セクションの一部。レッスン 15/27。
各モデルは1つの役割に絞りましょう。スコアは1つのクラスに、残りライフは別のクラスにします。小さなモデルは読みやすく、ウィジェットは必要なものだけを監視します。複数のモデルを持つアプリには、複数のプロバイダーが必要です。
プロバイダーを入れ子にして、1つのプロバイダーを次のプロバイダーの子にすることもできますが、モデルが増えるたびにコードが右へずれていきます。MultiProviderなら、代わりにフラットなリストを使えます。
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => Score()),
ChangeNotifierProvider(create: (context) => Lives()),
],
child: const MyApp(),
),
);リスト内のプロバイダーには、それぞれ独自のchildはありません。MultiProviderがそれらを積み重ね、すべての下にchildを配置します。その下にあるすべてのウィジェットは、型を指定して、どのモデルでも監視または読み取りできます。たとえば、context.watch<Lives>()です。
チャレンジ
簡単ゲームページは2つのモデル、ScoreとLivesを監視していますが、mainが提供するのはスコアだけなので、アプリにエラーが表示されます。
mainのプロバイダーを、両方のモデルを提供するMultiProviderに置き換えてください。
自分で試してみよう
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Score extends ChangeNotifier {
int _points = 0;
int get points => _points;
void hit() {
_points += 10;
notifyListeners();
}
}
class Lives extends ChangeNotifier {
int _left = 3;
int get left => _left;
void miss() {
if (_left > 0) {
_left--;
notifyListeners();
}
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Score(),
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: GamePage(),
);
}
}
class GamePage extends StatelessWidget {
const GamePage({super.key});
@override
Widget build(BuildContext context) {
final points = context.watch<Score>().points;
final lives = context.watch<Lives>().left;
return Scaffold(
appBar: AppBar(title: Text('Lives: $lives')),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Points: $points', style: const TextStyle(fontSize: 40)),
const SizedBox(height: 16),
Row(
mainAxisSize: MainAxisSize.min,
children: [
ElevatedButton(
onPressed: () => context.read<Score>().hit(),
child: const Text('Hit'),
),
const SizedBox(width: 16),
ElevatedButton(
onPressed: () => context.read<Lives>().miss(),
child: const Text('Miss'),
),
],
),
],
),
),
);
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
状態管理のすべてのレッスン
3Provider
Provider:Modelを共有するnotifyListenersを呼び出すProvider:WatchとReadProvider:Consumer2つの画面、1つのModelModel内のオブジェクトのリスト複数のModel:MultiProvider自分で練習してみよう: Flutterオンラインコンパイラ