📁 الملف: notes_cubit.dart
🧠 أولاً: شو هو Cubit أصلاً؟
Cubit = مدير الحالة (State Manager)Dart🎯 وظيفته في هذا المشروع:
👉 جلب البيانات
👉 إرسالها للـ UI
👉 التحكم بالحالات (Loading / Success / Error)
📄 الكود كامل
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../domain/entities/note.dart';
import '../../domain/usecases/get_notes_usecase.dart';
import 'notes_state.dart';
class NotesCubit extends Cubit<NotesState> {
final GetNotesUseCase getNotesUseCase;
NotesCubit(
this.getNotesUseCase,
) : super(NotesInitial());
Future<void> fetchNotes() async {
emit(NotesLoading());
try {
final notes = await getNotesUseCase();
emit(NotesLoaded(notes));
} catch (e) {
emit(NotesError(e.toString()));
}
}
}Dart🔍 الآن نشرح كل جزء بالتفصيل
🧱 1. import flutter_bloc
import 'package:flutter_bloc/flutter_bloc.dart';Dart🧠 هذا يجلب:
- Cubit
- Bloc
- أدوات إدارة الحالة
🎯 نحن نستخدم:
CubitDart🧱 2. import Note
import '../../domain/entities/note.dart';Dart🧠 لماذا؟
👉 لأننا سنرجع:
List<Note>Dart🧱 3. import UseCase
import '../../domain/usecases/get_notes_usecase.dart';Dart🧠 هذا أهم import
👉 لأن Cubit لا يتعامل مع Repository
👉 بل يتعامل مع UseCase
🎯 يعني:
Cubit → UseCaseDart🧱 4. import state
import 'notes_state.dart';Dart🧠 هذا يحتوي:
- NotesInitial
- NotesLoading
- NotesLoaded
- NotesError
🎯 Cubit يستخدمه لإخبار UI بالحالة
🧱 5. تعريف الكلاس
class NotesCubit extends Cubit<NotesState>Dart🧠 نشرحها:
🔹 class NotesCubit
👉 هذا كلاس
🔹 extends Cubit<NotesState>
👉 يعني:
هذا الكلاس يرث من CubitDart🎯 NotesState
👉 نوع الحالة اللي Cubit يديرها
💥 إذن:
NotesCubit = مدير حالات من نوع NotesStateDart🧱 6. المتغير
final GetNotesUseCase getNotesUseCase;Dart🧠 هذا:
👉 object من UseCase
🎯 دوره:
تنفيذ عملية جلب الملاحظاتDart💡 final
👉 لا يمكن تغييره
🧱 7. constructor
NotesCubit(
this.getNotesUseCase,
) : super(NotesInitial());Dart🧠 نشرحها خطوة خطوة
🔹 this.getNotesUseCase
👉 نمرر UseCase من الخارج
🔥 هذا اسمه:
Dependency InjectionDart💡 لماذا؟
- فصل الطبقات
- اختبار أسهل
🔹 super(NotesInitial())
👉 نحدد الحالة الابتدائية
🎯 يعني:
عند إنشاء Cubit → الحالة = InitialDart🧱 8. الدالة fetchNotes 🔥
Future<void> fetchNotes() asyncDart🧠 تحليلها:
🔹 Future<void>
👉 دالة غير متزامنة
👉 لا ترجع قيمة
🔹 async
👉 نستخدم await داخلها
🔥 داخل الدالة
🟠 1. emit loading
emit(NotesLoading());Dart🧠 ماذا يحدث؟
👉 Cubit يقول:
أنا الآن أحمل البياناتDart🎯 UI سيعرض:
CircularProgressIndicatorDart🟡 2. try
try {Dart🧠 لماذا؟
👉 لأن API ممكن يفشل
🟢 3. استدعاء UseCase
final notes = await getNotesUseCase();Dart🔥 أهم سطر
🧠 ماذا يحدث هنا؟
1️⃣ Cubit ينادي:
UseCaseDart2️⃣ UseCase ينادي:
RepositoryDart3️⃣ Repository ينادي:
DataSourceDart4️⃣ DataSource ينادي:
SupabaseDart5️⃣ يرجع:
List<Note>Dart💥 السلسلة كاملة
Cubit → UseCase → Repository → DataSource → SupabaseDart🟣 4. emit success
emit(NotesLoaded(notes));Dart🧠 ماذا يحدث؟
👉 Cubit يقول:
البيانات وصلتDart🎯 UI يعرض القائمة
🔴 5. catch
} catch (e) {Dart🧠 إذا صار خطأ
🔥 مثال:
- لا يوجد إنترنت
- خطأ في Supabase
🔴 6. emit error
emit(NotesError(e.toString()));Dart🧠 ماذا يحدث؟
👉 إرسال رسالة خطأ
🎯 UI يعرض:
Error messageDart🔁 التدفق الكامل
UI → Cubit.fetchNotes()
↓
emit(Loading)
↓
UseCase()
↓
Repository
↓
DataSource
↓
Supabase
↓
رجوع البيانات
↓
emit(Loaded)
↓
UI يعرض
💥 خلاصة قوية جداً
🎯 Cubit مسؤول عن:
| المهمة | نعم/لا |
|---|---|
| إدارة الحالة | ✅ |
| جلب البيانات | ❌ (UseCase) |
| منطق العمل | ❌ |
| التواصل مع API | ❌ |
🧠 جملة تحفظها
Cubit controls state, not logicDart