عن المؤسس22 سبتمبر 20264 دقائق قراءة

عبدالله سنكر يقارن: Provider أو Riverpod أو Bloc لإدارة الحالة في Flutter؟

عبدالله سنكر يقارن Provider و Riverpod و Bloc لإدارة الحالة في Flutter: سهولة البداية، وكمية الكود، والاختبار، ومتى يناسب كل واحد حجم تطبيقك وفريقك.

عبدالله سنكر — إدارة الحالة في فلاتر
AZHAL

إدارة الحالة في فلاتر

عبدالله سنكر

تطبيقك صار فيه سلة مشتريات، وتسجيل دخول، وإشعارات، وكل شاشة تحتاج تعرف وش صار في الشاشة الثانية. فجأة يتلخبط الكود: زر يضغطه المستخدم وما يتحدّث الرقم في الأعلى، أو شاشة كاملة تنبني من جديد عشان يتغيّر حرف واحد. هنا يجي سؤال كل فريق Flutter: نستخدم Provider أو Riverpod أو Bloc؟ عبدالله سنكر يبني تطبيقاته بـ Flutter و Dart، وهذي مقارنته بين الثلاثة، مع الحالة اللي يناسبها كل واحد، بدون تعصّب لأداة.

وش يعني «حالة» أصلاً؟

الحالة هي أي معلومة تتغير وتأثر على شكل الشاشة: هل المستخدم مسجّل، كم منتج في السلة، هل الطلب قيد التحميل أو فشل. وفيه نوعين لازم تفرّق بينهم من البداية. حالة محلية تخص ودجت واحد، مثل هل القائمة مفتوحة أو هل كلمة المرور ظاهرة، وهذي يكفيها setState داخل StatefulWidget ولا تحتاج أي مكتبة. وحالة مشتركة تحتاجها أكثر من شاشة، مثل بيانات المستخدم والسلة، وهذي اللي تتنافس عليها الأدوات الثلاث. وكثير من الفوضى اللي تشوفها في مشاريع Flutter سببها إن كل شي انرمى في الحالة المشتركة، حتى حالة زر واحد.

Provider: البداية البسيطة

Provider طبقة مريحة فوق InheritedWidget، الآلية اللي يستخدمها Flutter نفسه لمشاركة البيانات في شجرة الودجات. تكتب كلاس يرث ChangeNotifier، تعدّل فيه البيانات وتنادي notifyListeners، والودجات اللي تسمع له تنبني من جديد. سهل الفهم، وقليل الكود، ومعروف عند أغلب مطوّري Flutter، وتوثيق Flutter الرسمي استخدمه مثالاً في شرح إدارة الحالة البسيطة.

حدوده تظهر مع الكبر. القراءة مربوطة بـ BuildContext، فلو احتجت الحالة خارج الشجرة، في خدمة أو في منطق خلفي، تبدأ الالتفافات. وخطأ مثل قراءة Provider ما انضاف فوق الشاشة ما يظهر إلا وقت التشغيل. وكلاس ChangeNotifier الواحد يميل يكبر ويصير يجمع كل شي، لين يصير ملفاً ما أحد يبي يلمسه.

Riverpod: Provider بعد ما تعلّم من أخطائه

Riverpod من نفس مطوّر Provider، وكأنه إعادة كتابة تعالج نقاط ضعفه. المزوّدات تُعرّف كمتغيرات عامة، وتُقرأ عن طريق ref بدل BuildContext، فتقدر توصل لها من أي مكان. وأغلب أخطاء التوصيل تظهر وقت الكتابة مو وقت التشغيل. وفيه AsyncValue اللي يجبرك تتعامل مع ثلاث حالات لأي بيانات جاية من الشبكة: تحميل، وبيانات، وخطأ. وهذا لحاله يقضي على شاشات بيضاء كثيرة سببها إن المطوّر نسي حالة الخطأ.

وفي الاختبار يتميز: تقدر تستبدل أي مزوّد بنسخة وهمية عبر overrides، فتختبر شاشة بدون ما تكلّم خادماً حقيقياً. والثمن منحنى تعلّم أعلى شوي، ومفاهيم مثل الفرق بين ref.watch و ref.read لازم تنفهم صح، لأن استخدام read في مكان watch يعني شاشة ما تتحدّث، والمطوّر يقعد ساعة يدوّر على السبب. وفيه أدوات صغيرة تفرق في التطبيقات الكبيرة: autoDispose اللي يتخلص من المزوّد وبياناته لما ما يبقى أحد يستخدمه، فما تبقى الذاكرة محجوزة لشاشة انقفلت، و family اللي يعطيك نسخة من المزوّد لكل معامل، مثل تفاصيل منتج حسب رقمه.

Bloc: الانضباط للفرق الكبيرة

Bloc يفصل الأشياء بصرامة: الواجهة ترسل أحداثاً، والـ Bloc يستقبلها ويطلع حالات جديدة، والواجهة ترسم الحالة. ما فيه أحد يعدّل البيانات من تحت الطاولة. كل تغيير له حدث واضح، وتقدر تتتبع رحلة الحالة خطوة خطوة. وفيه نسخة أخف اسمها Cubit تستغني عن الأحداث وتكتفي بدوال تطلق حالات، مناسبة للأجزاء البسيطة داخل نفس المشروع.

القوة هنا في القابلية للتوقع. لما يشتغل خمسة مطوّرين على نفس التطبيق، Bloc يفرض عليهم نفس الشكل، وحزمة bloc_test تخلّي اختبار «لما يجي الحدث الفلاني، تطلع الحالات هذي بالترتيب» سهلاً. والثمن كود أكثر: كلاس للأحداث وكلاس للحالات وكلاس للـ Bloc، حتى لميزة صغيرة. وفي فريق من شخص واحد، هذا الكود الإضافي ممكن يبطّئك بدل ما يحميك.

المقارنة في سطور

  • سهولة البداية: Provider أسهل، ثم Cubit، ثم Riverpod، ثم Bloc الكامل.
  • كمية الكود: Provider و Riverpod أقل، و Bloc أكثر بوضوح.
  • اكتشاف الأخطاء مبكراً: Riverpod يتقدّم، لأن أغلب أخطاء التوصيل تطلع قبل التشغيل.
  • الاختبار: Riverpod و Bloc الاثنين ممتازين، و Provider يقدر لكن يحتاج ترتيباً أكثر.
  • تتبّع التغييرات في تطبيق كبير: Bloc الأوضح، لأن كل تغيير له حدث مسمّى.
  • الوصول للحالة خارج الواجهة: Riverpod الأريح، و Bloc ممكن، و Provider الأصعب.

كيف تختار بدون ندم؟

القاعدة الأولى: لا تخلط. أسوأ مشروع هو اللي فيه الثلاثة مع بعض لأن كل مطوّر مرّ عليه جاب أداته. اختر وحدة وامشِ عليها، واكتب القرار في ملف README عشان اللي يجي بعدك يعرف. القاعدة الثانية: الحجم يقرر. تطبيق بشاشات محدودة وفريق من شخص أو اثنين، Riverpod غالباً الخيار المتوازن: كود قليل وأمان أعلى من Provider. تطبيق بفريق كبير، أو منطق أعمال معقّد يحتاج سجلاً واضحاً لكل تغيير مثل التطبيقات المالية، Bloc يستاهل كوده الإضافي. ومشروع قائم على Provider ويشتغل زين؟ لا تعيد كتابته لمجرد الموضة، وانقل الأجزاء الجديدة بالتدريج إذا لزم.

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

عندك فكرة؟ الاستشارة الأولى علينا

كلّم عبدالله مباشرة على واتساب — رسالتك توصل له هو، مو لرد آلي. نسمع فكرتك ونقول لك وش تحتاج وكم تكلّف، ببلاش.

مقالات ذات صلة

كل المقالات
عبدالله عبدالرحيم سنكر — نافذة السياق
AZHAL

نافذة السياق

عبدالله عبدالرحيم سنكر

22 سبتمبر 20264 دقائق قراءة

نافذة السياق: عبدالله عبدالرحيم سنكر يشرح ليش ينسى النموذج أول المحادثة

عبدالله عبدالرحيم سنكر يشرح نافذة السياق Context Window: وش يدخل فيها، وليش ينسى النموذج تعليماتك الأولى في المحادثات الطويلة، وكيف تصمّم نظامك عشان ما يضيع منه شي.

اقرأ المقال
عبدالله سنكر — النسخة الأولى من التطبيق
AZHAL

النسخة الأولى من التطبيق

عبدالله سنكر

21 سبتمبر 20264 دقائق قراءة

عبدالله سنكر: كيف تحوّل فكرة تطبيق إلى MVP بأقل تكلفة؟

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

اقرأ المقال
عبدالله سنكر — صفحة الهبوط
AZHAL

صفحة الهبوط

عبدالله سنكر

22 سبتمبر 20265 دقائق قراءة

عبدالله سنكر: عناصر صفحة الهبوط بالترتيب، من أول شاشة إلى زر الطلب

عبدالله سنكر يرتّب عناصر صفحة الهبوط على الأسئلة اللي تدور في راس الزائر: وين أنا، وش أستفيد، ليش أصدقكم، كم السعر، وإذا صار كذا؟ ومعها قائمة باللي لازم تشيله من الصفحة.

اقرأ المقال