استخدام Provider مع Flutter لإدارة حالة التطبيق


الناشر: Flutter Learning

القسم: استخدام visual studio code

تاريخ النشر: 2022-12-28



ماهو الـ Provider ؟

هو اسهل طريقة لادارة بيانات التطبيق، بالاضافة للتوصية من Flutter باستخدامة، بالاضافة الى وصف كاتب الحزمة. ليس مجرد عرض للقيم، ولكن يمكنك إنشاؤها ومتابعتها وايضاً التخلص منها. عند اضافة Provider إلى Widget Tree فيمكنك الوصول الى قيمة الـ Provider في أي مكان من التطبيق.






اضافة provider الى التطبيق

الآن يمكن اخذنا فكره من الـ Provider ولكن كيف نقدر نستخدمة ؟ انشئ مشروع Flutter جديد وقم باضافة الـ Provider الى dependencies . يوجد طريقة اسهل واجمل لاضافة الحزم الى مشروعك، فقط استخدم هذا الامر فيد مسار مشروعك.



code
نسخ
اقتباس
عرض
تنزيل
	
								
flutter pub add provider


سيقوم هذا الأمر بإضافة آخر اصدار من الحزمة لمشروعك.





سنقوم بإنشاء واجهة بسيطة تحتوي على Button ينفذ عملية و Text يعرض نتائج العملية، حتى يكون الشرح سهل وواضح بعيد عن التعقيدات.





code
نسخ
اقتباس
عرض
تنزيل
	
								
class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Provider"), ), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Container( padding: const EdgeInsets.all(50), child: Text('النتيجة'), ), Container( padding: const EdgeInsets.all(20), child: ElevatedButton( child: Text('تنفيذ الامر'), onPressed: () {}, ), ), ], ), ); } }


لا يوجد في الكود السابق شئ مميز ، عمود يوجد فيه Widgets، سنقوم الآن باضافة Provider. Provider هو أبسط Widget يوجد في الحزمة، يقوم بالعادة بالتعامل مع Object ولكن لا يساعد ابدا في تحديث الواجهة في حال حدوث تغيير للبيانات، كما ستلاحظ عند الضغط على الـ Button لا يوجد تحديث أو تغيير للبيانات. سنقوم بإنشاء الـ Object الذي سنتعامل معه وهو بسييييييط جدا.



user.dart

code
نسخ
اقتباس
عرض
تنزيل
	
								
class User { String name = 'Flutter'; void action() { name = 'Provider'; } }


الآن سنقوم بتعديل واجهة التطبيق واضافة Provider Widget إلى الواجهة واستخدام Consumer Widget واضافة Model الذي قمنا بانشائه.



my_home_page.dart

code
نسخ
اقتباس
عرض
تنزيل
	
								
class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Provider( create: (context) => User(), child: Scaffold( appBar: AppBar( title: Text("Provider"), ), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Consumer<User>( builder: (context, model, child) => Container( padding: const EdgeInsets.all(50), child: Text(model.name), ), ), Consumer<User>( builder: (context, model, child) => Container( padding: const EdgeInsets.all(20), child: ElevatedButton( child: Text('تنفيذ الامر'), onPressed: () { model.action(); }, ), ), ), ], ), ), ); } }


نلاحظ اضفنا Provider و قمنا أيضا باضافة User الى create، بالاضافة قمنا باستخدام Consumer على Text و Button ايضاً، داخل Text وصلنا لقيم User وهو name وداخل Button اضفنا العملية وهي action. لكن بعد كل هذه التعديلات لن تتغير القيمة إذا قمنا بالضغط على Button. الاختلاف اننا استطعنا الوصول لقيمة المتغير name في User.



كيف نقدر نغير القيمة إذا المستخدم ضغط الـ Button ؟

يمكن من خلال استخدام ChnageNotifireProvider



استخدام ChnageNotifireProvider

هنا سيقوم Widget لمتابعة التغييرات في User وعند حدوث أي تغيير في البيانات سيقوم بإعادة بناء Widget وعرض القيم الجديدة. سنقوم بتعديل User ونضيف ChangeNotifre عند حدوث تغيير سيقوم ChangeNotifireProvider بإعادة بناء اي Widget تحت Consumer٫



user.dart

code
نسخ
اقتباس
عرض
تنزيل
	
								
class User with ChangeNotifier { String name = 'Flutter'; void action() { name = 'Provider'; notifyListeners(); } }


my_home_page.dart

code
نسخ
اقتباس
عرض
تنزيل
	
								
class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) => User(), child: Scaffold( appBar: AppBar( title: Text("Provider"), ), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Consumer<User>( builder: (context, model, child) => Container( padding: const EdgeInsets.all(50), child: Text(model.name), ), ), Consumer<User>( builder: (context, model, child) => Container( padding: const EdgeInsets.all(20), child: ElevatedButton( child: Text('تنفيذ الامر'), onPressed: () { model.action(); }, ), ), ), ], ), ), ); } }


الان اصبحت البيانات تتغير عن الضغط على Button ولكن اذا لاحظت ان Widget تحت Consumer Widget, لكن مانحتاج نعيد بناء Button لأن لايوجد قيمة متغيرة للدالة Action. سنقوم بتعديل بسيط على الكود.



code
نسخ
اقتباس
عرض
تنزيل
	
								
class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return ChangeNotifierProvider( create: (context) => User(), child: Scaffold( appBar: AppBar( title: Text("Provider"), ), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Consumer<User>( builder: (context, model, child) => Container( padding: const EdgeInsets.all(50), child: Text(model.name), ), ), Container( padding: const EdgeInsets.all(20), child: Button(), ), ], ), ), ); } } class Button extends StatelessWidget { const Button({ Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return ElevatedButton( child: Text('تنفيذ الامر'), onPressed: () => Provider.of<User>(context, listen: false).action(), ); } }


استخدام MultiProvider

في حال وجود اكثر من Provider كيف نقدر ان نتعامل معها ؟ نفرض ان عندنا Data Model ثاني خاص بعمر المستخدم، سنقوم باستخدام MultiProvider .



حقيقة لا يوجد اي اختلاف بين استخدام Provider او Multi Provider الا في طريقة اضافتها للمشروع، اولا سنقوم بانشاء Data Model للـAge بعد ذلك سنقوم بتعديل الكود لاستخدام اكثر من Provider .



age.dart

code
نسخ
اقتباس
عرض
تنزيل
	
								
class Age with ChangeNotifier { int age = 0; void action() { age++; notifyListeners(); } }


my_home_page.dart

code
نسخ
اقتباس
عرض
تنزيل
	
								
class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return MultiProvider( providers: [ ChangeNotifierProvider<User>(create: (context) => User()), ChangeNotifierProvider<Age>(create: (context) => Age()), ], child: Scaffold( appBar: AppBar( title: Text("Provider"), ), body: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ Consumer<User>( builder: (context, model, child) => Container( padding: const EdgeInsets.all(50), child: Text(model.name), ), ), Container( padding: const EdgeInsets.all(20), child: Button(), ), Consumer<Age>( builder: (context, model, child) => Container( padding: const EdgeInsets.all(50), child: Text('${model.age}'), ), ), Container( padding: const EdgeInsets.all(20), child: AgeButton(), ), ], ), ), ); } } class Button extends StatelessWidget { const Button({ Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return ElevatedButton( child: Text('تغيير الاسم '), onPressed: () => Provider.of<User>(context, listen: false).action(), ); } } class AgeButton extends StatelessWidget { const AgeButton({ Key? key, }) : super(key: key); @override Widget build(BuildContext context) { return ElevatedButton( child: Text('تغيير العمر'), onPressed: () => Provider.of<Age>(context, listen: false).action(), ); } }


سلة المشتريات افراغ السلة