BlocProvider BlocBuilder

BlocProvider
BlocBuilder

خليني أشرحهم لك بعمق + منطق + كود + كيف يشتغلوا مع بعض


🧩 أولًا: BlocProvider

🎯 ما وظيفته؟

👉 هو المسؤول عن:

إنشاء الـ Cubit وتوفيره (Inject) لباقي التطبيق

بمعنى:

يخلي أي Widget داخل الشجرة يقدر يوصل للـ Cubit


🔧 شكله في الكود

BlocProvider(
create: (context) => CounterCubit(),
child: HomePage(),
)

🧠 ماذا يحدث هنا؟

1️⃣ إنشاء Cubit

create: (context) => CounterCubit()

👉 يتم إنشاء نسخة من:

CounterCubit()

2️⃣ توفيره في الشجرة (Widget Tree)

BlocProvider

HomePage

أي Widget داخلها

👉 كل Widget تحت HomePage يمكنه الوصول للـ Cubit


📥 كيف نصل للـ Cubit؟

داخل أي Widget:

context.read<CounterCubit>()

أو:

BlocProvider.of<CounterCubit>(context)

🔥 مثال عملي

زر زيادة:

ElevatedButton(
onPressed: () {
context.read<CounterCubit>().increment();
},
child: Text("زيادة"),
)

⚠️ بدون BlocProvider؟

❌ سيحدث خطأ:

BlocProvider.of() called with a context that does not contain a Bloc

💡 خلاصة BlocProvider

الوظيفةالشرح
إنشاء Cubitcreate
توفيرهلكل الشجرة
الوصول لهcontext.read

🧩 ثانيًا: BlocBuilder

🎯 ما وظيفته؟

👉 هو المسؤول عن:

الاستماع للتغييرات (emit) وإعادة بناء الواجهة


🔧 شكله في الكود

BlocBuilder<CounterCubit, CounterState>(
builder: (context, state) {
return Text("${state.counter}");
},
)

🧠 ماذا يحدث هنا؟

1️⃣ يستمع للـ Cubit

CounterCubit

2️⃣ ينتظر أي emit

emit(CounterState(...))

3️⃣ عند وصول حالة جديدة

👉 يتم تشغيل:

builder(context, state)

🔄 دورة العمل

emit() → BlocBuilder يسمع → يعيد بناء UI

🔥 مثال حي

BlocBuilder<CounterCubit, CounterState>(
builder: (context, state) {
return Column(
children: [
Text("${state.counter}"),
ElevatedButton(
onPressed: () {
context.read<CounterCubit>().increment();
},
child: Text("زيادة"),
),
],
);
},
)

🧠 ماذا يحدث عند الضغط؟

  1. الضغط على الزر
  2. استدعاء increment()
  3. داخلها emit()
  4. BlocBuilder يسمع
  5. يعيد بناء Text
  6. يظهر الرقم الجديد

🔗 العلاقة بين BlocProvider و BlocBuilder

🧩 كيف يعملوا مع بعض؟

BlocProvider → يوفر Cubit
BlocBuilder → يسمع من Cubit

🔄 التسلسل الكامل

BlocProvider

CounterCubit (state = 0)

BlocBuilder (يعرض 0)

زر + يضغط

increment()

emit(1)

BlocBuilder يعيد البناء

يعرض 1

⚠️ الفرق المهم جدًا

العنصرالوظيفة
BlocProviderإنشاء + توفير
BlocBuilderعرض + تحديث

🔥 مثال كامل (مهم جدًا)

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CounterCubit(),
child: Scaffold(
body: Center(
child: BlocBuilder<CounterCubit, CounterState>(
builder: (context, state) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("${state.counter}"),
ElevatedButton(
onPressed: () {
context.read<CounterCubit>().increment();
},
child: Text("زيادة"),
),
],
);
},
),
),
),
);
}
}

🧠 ملاحظات احترافية

read vs watch

الطريقةمتى تستخدمها
readتنفيذ دالة (بدون rebuild)
watchالاستماع للتغييرات

✅ BlocBuilder لا يُنشئ Cubit

👉 فقط يستمع


✅ يمكن استخدام أكثر من BlocProvider

MultiBlocProvider(
providers: [
BlocProvider(create: (_) => CounterCubit()),
BlocProvider(create: (_) => AnotherCubit()),
],
child: MyApp(),
)

💥 الخلاصة النهائية

  • BlocProvider = يعطيك Cubit
  • BlocBuilder = يسمع ويحدث الواجهة
  • emit = يرسل التحديث