شاشتان ونموذج واحد
جزء من قسم إدارة الحالة في رحلة Flutter على Coddy. الدرس 13 من 27.
تظهر فائدة Provider عندما تتشارك شاشتان البيانات. تغيّر شاشة الإعدادات الاسم، وتعرضه الشاشة الرئيسية، من دون أن تمرّر أيٌّ من الشاشتين شيئًا إلى الأخرى.
موضع provider مهم. يحتوي MaterialApp على Navigator، وكل شاشة تدفعها تُضاف إليه بجوار home، لا بداخله:
ChangeNotifierProvider <- above MaterialApp: every screen finds it
MaterialApp
Navigator
HomePage
SettingsScreen <- pushed next to HomePageلا يصل provider المُغلَّف حول HomePage إلا إلى HomePage. فالشاشة المدفوعة ليست تحته، ولذلك لا يمكنها العثور على النموذج. ضع provider فوق MaterialApp، في main، وستتشاركه كل الشاشات.
لا تُصلح الخطأ بإضافة ChangeNotifierProvider ثانٍ إلى الشاشة الأخرى. فهذا ينشئ نموذجًا ثانيًا: يختفي الخطأ، لكن الشاشات لا تعود تتشارك أي شيء.
التحدي
متوسطاضغط على رمز الترس، واكتب اسمًا، ثم اضغط على Save: سيعرض التطبيق خطأً، لأن المزوّد يغلّف HomePage فقط.
- انقل
ChangeNotifierProviderإلى خارجMyAppوضعه داخلmain، حولMyApp.
بعد ذلك، يؤدي حفظ Ada إلى عرض Hello, Ada! في الصفحة الرئيسية.
جرّب بنفسك
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Profile extends ChangeNotifier {
String _name = 'Guest';
String get name => _name;
void rename(String newName) {
_name = newName;
notifyListeners();
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProvider(
create: (context) => Profile(),
child: const HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
final profile = context.watch<Profile>();
return Scaffold(
appBar: AppBar(
title: const Text('Home'),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const SettingsScreen()),
);
},
),
],
),
body: Center(
child: Text('Hello, ${profile.name}!', style: const TextStyle(fontSize: 32)),
),
);
}
}
class SettingsScreen extends StatefulWidget {
const SettingsScreen({super.key});
@override
State<SettingsScreen> createState() => _SettingsScreenState();
}
class _SettingsScreenState extends State<SettingsScreen> {
final controller = TextEditingController();
@override
Widget build(BuildContext context) {
final profile = context.watch<Profile>();
return Scaffold(
appBar: AppBar(title: const Text('Settings')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text('Signed in as ${profile.name}'),
const SizedBox(height: 16),
TextField(
controller: controller,
decoration: const InputDecoration(labelText: 'Your name'),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
context.read<Profile>().rename(controller.text);
Navigator.pop(context);
},
child: const Text('Save'),
),
],
),
),
);
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس إدارة الحالة
تدرّب بنفسك: مترجم Flutter عبر الإنترنت