عدة نماذج: MultiProvider
جزء من قسم إدارة الحالة في رحلة Flutter على Coddy. الدرس 15 من 27.
اجعل كل نموذج مسؤولًا عن شيء واحد: النقاط في نموذج، والأرواح في نموذج آخر. النماذج الصغيرة سهلة القراءة، ولا يراقب عنصر واجهة المستخدم إلا ما يحتاج إليه. يحتاج التطبيق الذي يضم عدة نماذج إلى عدة موفّرات.
يمكنك تداخلها، بحيث يكون أحد الموفّرات عنصرًا فرعيًا للذي يسبقه، لكن الشيفرة تنزاح نحو اليمين مع كل نموذج. يأخذ MultiProvider قائمة مسطحة بدلًا من ذلك:
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => Score()),
ChangeNotifierProvider(create: (context) => Lives()),
],
child: const MyApp(),
),
);لا يكون للموفّرات في القائمة عنصر child خاص بها: إذ يرتّبها MultiProvider لك ويضع child تحتها جميعًا. يمكن لكل عنصر واجهة مستخدم أدناه مراقبة أي نموذج أو قراءته، كلٌّ بحسب نوعه: context.watch<Lives>().
التحدي
سهلتراقب صفحة اللعبة نموذجين، 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'),
),
],
),
],
),
),
);
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس إدارة الحالة
تدرّب بنفسك: مترجم Flutter عبر الإنترنت