📁 lib/main.dart
🧠 شرح الملف
هذا الملف هو:
نقطة بداية التطبيق + ربط كل الطبقات مع بعض (Dependency Injection)Dart📄 الكود الكامل:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'core/supabase/supabase_client.dart';
import 'features/notes/data/datasource/notes_remote_datasource.dart';
import 'features/notes/data/repository/notes_repository_impl.dart';
import 'features/notes/domain/usecases/get_notes_usecase.dart';
import 'features/notes/presentation/cubit/notes_cubit.dart';
import 'features/notes/presentation/pages/notes_page.dart';
void main() async {
/// لازم قبل أي async
WidgetsFlutterBinding.ensureInitialized(); /// تهيئة Supabase
await Supabase.initialize(
url: 'YOUR_URL',
anonKey: 'YOUR_ANON_KEY',
);
/// الحصول على client
final client = SupabaseConfig.client;
/// 🔗 ربط الطبقات (Dependency Injection) /// DataSource
final dataSource = NotesRemoteDataSource(client);
/// Repository
final repo = NotesRepositoryImpl(dataSource);
/// UseCase
final getNotes = GetNotesUseCase(repo);
/// تشغيل التطبيق
runApp(MyApp(getNotes));
}
class MyApp extends StatelessWidget {
final GetNotesUseCase getNotes;
const MyApp(this.getNotes, {super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
/// إنشاء Cubit
create: (_) => NotesCubit(getNotes)..fetchNotes(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: NotesPage(),
),
);
}
}Dart🧠 أهم نقطة هنا
NotesCubit(getNotes)..fetchNotes()Dart👉 هذا يعني:
أنشئ Cubit → مباشرة نفّذ fetchNotesDartالملف: main.dart
🧠 أولاً: ما وظيفة هذا الملف؟
تشغيل التطبيق + تهيئة الخدمات + ربط الطبقات (Dependency Injection)Dart📄 الكود
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Supabase.initialize(
url: 'YOUR_URL',
anonKey: 'YOUR_ANON_KEY',
);
final client = SupabaseConfig.client;
final dataSource = NotesRemoteDataSource(client);
final repo = NotesRepositoryImpl(dataSource);
final getNotes = GetNotesUseCase(repo);
runApp(MyApp(getNotes));
}Dart🔍 نشرح خطوة خطوة
🧱 1. main()
void main() asyncDart🧠 هذا:
👉 نقطة بداية التطبيق
🔥 async
👉 لأننا سنستخدم:
await Supabase.initialize()Dart🧱 2. ensureInitialized
WidgetsFlutterBinding.ensureInitialized();Dart🧠 معناها:
تأكد أن Flutter جاهز قبل أي async أو pluginDart🎯 لماذا مهم هنا؟
لأن:
Supabase.initialize()Dartيحتاج Flutter يكون جاهز
🧱 3. تهيئة Supabase
await Supabase.initialize(
url: 'YOUR_URL',
anonKey: 'YOUR_ANON_KEY',
);Dart🧠 ماذا يحدث؟
👉 يتم ربط التطبيق مع Supabase
🎯 URL
👉 رابط المشروع
🎯 anonKey
👉 مفتاح الوصول
🧱 4. الحصول على client
final client = SupabaseConfig.client;Dart🧠 هذا:
👉 object يمثل الاتصال مع Supabase
💡 لماذا عبر class؟
حتى نستخدمه بكل المشروع بدون تكرارDart🧱 5. DataSource
final dataSource = NotesRemoteDataSource(client);Dart🧠 ماذا فعلنا؟
👉 أنشأنا الطبقة التي تتواصل مع Supabase
🔗 العلاقة:
DataSource → SupabaseDart🧱 6. Repository
final repo = NotesRepositoryImpl(dataSource);Dart🧠 ماذا فعلنا؟
👉 ربطنا Domain مع Data
🔗 العلاقة:
Repository → DataSourceDart🧱 7. UseCase
final getNotes = GetNotesUseCase(repo);Dart🧠 ماذا فعلنا؟
👉 أنشأنا عملية:
جلب الملاحظاتDart🔗 العلاقة:
UseCase → RepositoryDart🧱 8. runApp
runApp(MyApp(getNotes));Dart🧠 ماذا يحدث؟
👉 تشغيل التطبيق
💡 تمرير getNotes
👉 حتى يصل إلى Cubit
🧱 الآن ننتقل إلى MyApp
📄 الكود
class MyApp extends StatelessWidget {
final GetNotesUseCase getNotes;
const MyApp(this.getNotes, {super.key});Dart🧠 هذا:
👉 StatelessWidget
🎯 لماذا؟
لأن:
لا يوجد state داخلي هناDart💡 getNotes
👉 dependency تم تمريرها من main
🧱 build()
@override<br>Widget build(BuildContext context) {Dart🧠 هذه:
👉 تبني واجهة التطبيق
🧱 BlocProvider
return BlocProvider(Dart🧠 أهم Widget هنا
👉 مسؤول عن:
توفير Cubit لكل الشجرةDart🧱 create
create: (_) => NotesCubit(getNotes)..fetchNotes(),Dart🔍 نفكها:
🔹 NotesCubit(getNotes)
👉 إنشاء Cubit
🔹 ..fetchNotes()
cascade operatorDart🧠 معناها:
NotesCubit(getNotes);
cubit.fetchNotes();Dart🎯 لماذا؟
👉 أول ما يشتغل التطبيق:
يجلب البيانات مباشرةDart🧱 MaterialApp
child: MaterialApp(Dart🧠 هذا:
👉 أساس التطبيق
🎯 يحتوي:
- routing
- theme
- home
🧱 debug banner
debugShowCheckedModeBanner: false,Dart🧠 إزالة:
شريط DEBUGDart🧱 الصفحة الرئيسية
home: NotesPage(),Dart🧠 هذه:
👉 أول شاشة تظهر
🔁 التسلسل الكامل
main()
↓
تهيئة Supabase
↓
إنشاء DataSource
↓
إنشاء Repository
↓
إنشاء UseCase
↓
runApp
↓
BlocProvider
↓
Cubit
↓
fetchNotes()
↓
UseCase
↓
Repository
↓
DataSource
↓
Supabase
↓
رجوع البيانات
↓
UI
💥 لماذا هذا التصميم قوي؟
🎯 1. فصل الطبقات
كل طبقة لها وظيفةDart🎯 2. مرونة
تبدل Supabase بدون كسر التطبيقDart🎯 3. قابل للاختبار
تقدر تعمل Mock بسهولةDart❗ المشكلة الحالية
🧠 main.dart فيه:
كثير dependenciesDart❌ مع 50 feature:
سيصبح فوضىDart🚀 الخطوة القادمة (التطوير)
🎯 الحل:
نستخدم get_it (Dependency Injection Container)Dart🔥 ماذا سنفعل؟
- نقل كل هذا إلى
injection.dart - جعل main نظيف جداً
- استخدام sl() بدل التمرير اليدوي
💥 الخلاصة
🧠 هذا الملف حالياً:
Bootstrap + WiringDart🧠 الجملة الذهبية:
main.dart should connect, not contain logicDart