كيفية التعامل مع الحالة في Flutter باستخدام نمط BLoC

في العام الماضي ، التقطت Flutter ويجب أن أقول إنها كانت رحلة رائعة حتى الآن. Flutter هو إطار عمل Google الرائع لتصميم تطبيقات عالية الجودة لنظامي التشغيل Android و iOS.

كما هو الحال مع إنشاء أي تطبيق تقريبًا ، هناك دائمًا حاجة للتعامل مع حالة التطبيق. من المهم أن يتم التعامل مع إدارة الدولة بكفاءة ، وذلك لتجنب تراكم الديون التقنية ، خاصةً مع نمو تطبيقك وتصبح أكثر تعقيدًا.

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

في هذه المقالة ، سنرى كيفية التعامل مع الحالة في Flutter باستخدام نمط BLoC.

يمكن تحقيق إدارة الحالة في Flutter بعدة طرق مختلفة:

عنصر واجهة مستخدم موروث : يتيح لك نشر البيانات إلى عناصر واجهة المستخدم الفرعية الخاصة به ويتم إعادة بناء عناصر واجهة المستخدم كلما حدث تغيير في حالة التطبيق. الجانب السلبي لاستخدام الفئة الأساسية InheritedWidget هو أن حالتك نهائية وهذا يثير مشكلة إذا كنت تريد تغيير حالتك.

نموذج النطاق : هذه حزمة خارجية مبنية على الجزء العلوي من InheritedWidget وتوفر طريقة أفضل قليلاً للوصول إلى الحالة وتحديثها وتغييرها. يسمح لك بتمرير نموذج بيانات بسهولة من عنصر واجهة مستخدم أصلي إلى أحفاده. بالإضافة إلى ذلك ، فإنه يعيد أيضًا بناء كل الأطفال الذين يستخدمون النموذج عند تحديث النموذج.

قد يثير هذا مشكلة في الأداء ، اعتمادًا على عدد ScopedModelDescendants التي يمتلكها النموذج ، حيث أعيد بناؤها عندما يكون هناك تحديث.

يمكن إصلاح هذه المشكلة عن طريق تحليل ScopedModel إلى نماذج متعددة حتى تحصل على تبعيات أكثر دقة. يؤدي تعيين rebuildOnChangeالعلم إلى falseإصلاح هذه المشكلة أيضًا ، ولكنه يجلب معها العبء المعرفي لتحديد الأداة التي يجب إعادة بنائها أم لا.

إعادة : نعم! كما هو الحال مع React ، هناك حزمة Redux تساعدك على إنشاء واستهلاك متجر Redux بسهولة في Flutter. مثل نظيره جافا سكريبت، وهناك عادة بضعة أسطر من التعليمات البرمجية النمطي وذهابا وإيابا من الإجراءات و مخفضات .

أدخل نمط BLoC

نمط مكون منطق الأعمال (BLoC) هو نمط تم إنشاؤه بواسطة Google وتم الإعلان عنه في مؤتمر Google I / O '18. يستخدم نمط BLoC البرمجة التفاعلية للتعامل مع تدفق البيانات داخل التطبيق.

يقف BLoC كوسيط بين مصدر البيانات في تطبيقك (على سبيل المثال ، استجابة API) والأدوات التي تحتاج إلى البيانات. يستقبل تدفقات الأحداث / البيانات من المصدر ، ويتعامل مع أي منطق أعمال مطلوب وينشر تدفقات تغييرات البيانات على عناصر واجهة المستخدم المهتمة بها.

كتلة اثنين من مكونات بسيطة: المصارف و تيارات ، وكلاهما يتم توفيرها من قبل StreamController . يمكنك إضافة تدفقات من إدخال الأحداث / البيانات إلى المغسلة والاستماع إليها كتدفقات من إخراج البيانات من خلال دفق .

A StreamController يمكن الوصول إليها من خلال ‘dart:async’مكتبة أو في شكل PublishSubject ، ReplaySubject أو BehaviourSubject عبر rxdartالحزمة.

يوجد أدناه مقتطف رمز يعرض BLoC بسيطًا:

import 'dart:async'; // import 'package:rxdart/rxdart.dart'; if you want to make use of PublishSubject, ReplaySubject or BehaviourSubject. // make sure you have rxdart: as a dependency in your pubspec.yaml file to use the above import class CounterBloc { final counterController = StreamController(); // create a StreamController or // final counterController = PublishSubject() or any other rxdart option; Stream get getCount => counterController.stream; // create a getter for our Stream // the rxdart stream controllers returns an Observable instead of a Stream void updateCount() { counterController.sink.add(data); // add whatever data we want into the Sink } void dispose() { counterController.close(); // close our StreamController to avoid memory leak } } final bloc = CounterBloc(); // create an instance of the counter bloc //======= end of CounterBloc file //======= somewhere else in our app import 'counter_bloc.dart'; // import the counter bloc file here @override void dispose() { bloc.dispose(); // call the dispose method to close our StreamController super.dispose(); } ... @override Widget build(BuildContext context) { return StreamBuilder( // Wrap our widget with a StreamBuilder stream: bloc.getCount, // pass our Stream getter here initialData: 0, // provide an initial data builder: (context, snapshot) => Text('${snapshot.data}'), // access the data in our Stream here ); } ...

A BLoC هي فئة Dart بسيطة. في مقتطف الشفرة أعلاه ، أنشأنا CounterBlocفئة StreamControllerوفيها ، أطلقنا عليها اسم counterController. أنشأنا جالبة لدينا تيار يسمى getCount، وهو updateCountالأسلوب الذي يضيف البيانات إلى دينا المغسلة عندما دعا، و disposeطريقة لإغلاق دينا StreamController.

للوصول إلى البيانات الموجودة في التدفق الخاص بنا ، أنشأنا StreamBuilderعنصر واجهة مستخدم وقمنا بتمرير التدفق الخاص بنا إلى streamممتلكاته والوصول إلى البيانات الموجودة في builderوظيفته.

تنفيذ BLoC

سنقوم بتحويل تطبيق نموذج Flutter الافتراضي لاستخدام BLoC. لنبدأ في إنشاء تطبيق Flutter جديد. في جهازك الطرفي ، قم بتشغيل الأمر التالي:

$ flutter create bloc_counter && cd bloc_counter

فتح التطبيق في محرر المفضلة لديك وإنشاء ثلاثة ملفات في مجلد ليب: counter.dart، counter_provider.dartو counter_bloc.dart.

لدينا CounterProviderسوف تحتوي على عدد صحيح وطريقة لزيادة ذلك. أضف الكود التالي إلى counter_provider.dartالملف:

class CounterProvider { int count = 0; void increaseCount() => count++; }

بعد ذلك ، سنقوم بتطبيق BLoC العداد الخاص بنا. أضف الكود أدناه إلى ملفك counter_block.dart:

في CounterBlocفصلنا ، استخدمنا جزءًا من نموذج الكود الأولي أعلاه. في السطر 7 ، أنشأنا CounterProviderالفصل الدراسي الخاص بنا وفي updateCountالطريقة ، قمنا باستدعاء طريقة الموفر لزيادة العدد ، ثم في السطر 13 ، مررنا العد إلى Sink الخاص بنا.

استبدل الكود الموجود في ملفك main.dartبالرمز أدناه. في الكود أدناه ، قمنا ببساطة بإزالة معظم كود العداد الافتراضي ، والذي سننقله إلى counter.dartملفنا. عندما incrementCounterيتم استدعاء الطريقة ، نقوم باستدعاء طريقة BLoC updateCountالتي تقوم بتحديث العدد وإضافته إلى حوضنا .

الآن ، يتلقى BLoC البيانات وتدفقها. يمكننا الوصول إلى تلك البيانات وعرضها على الشاشة من خلال StreamBuilder . نقوم بلف أي عنصر واجهة مستخدم يحتاج إلى البيانات في عنصر واجهة مستخدم StreamBuilder ونقوم بتمرير الدفق الذي يحتوي على البيانات إليه. أضف الكود التالي إلى counter.dartالملف:

في الكود أعلاه ، لدينا عنصر واجهة مستخدم ذي حالة. في فئة الولاية الخاصة بنا ، في السطر 13 ، نسمي طريقة التخلص الخاصة بنا ، بحيث يمكن إغلاق وحدة التحكم في التدفق كلما تمت إزالة عنصر واجهة المستخدم من الشجرة.

في السطر 19 ، نعيد عنصر واجهة مستخدم StreamBuilder والخط 20 ، ونقوم بتمرير أداة الحصول على الدفق الخاص بنا إليه وكذلك البيانات الأولية في السطر 21. يحتوي StreamBuilder أيضًا على عنصر builderيتيح لنا الوصول إلى البيانات عبر ملف snapshot. في السطر 30 ، نصل إلى البيانات ونعرضها في اللقطة.

انطلق وقم بتشغيل التطبيق عن طريق تشغيل الأمر أدناه. تأكد من تشغيل محاكي.

$ flutter run

أثناء تشغيل تطبيقك ، انقر فوق رمز علامة الجمع وشاهد زيادة العداد مع كل نقرة.

تمكنا معًا من تنفيذ أبسط أشكال BLoC في Flutter. يظل المفهوم كما هو بغض النظر عن حالة الاستخدام الخاصة بك.

أتمنى أن تكون قد وجدت هذه المقالة مفيدة. الرجاء القيام والمشاركة حتى يتمكن الآخرون من العثور على هذه المقالة. تواصل معي على Twitterdevelopia_ مع الأسئلة أو للدردشة.