لماذا State Management ضروري؟
في تطبيق بسيط (عدّاد)، setState يكفي. لكن حين يكبر التطبيق:
- البيانات تتنقّل بين شاشات
- نفس البيانات تُستخدم في أماكن كثيرة
- تحديث واحد يجب أن يظهر في عدّة widgets
هنا تحتاج state management صحيح.
الخيارات الثلاثة الأشهر
1. Provider — الرسمي القديم
الحلّ الذي كان يوصي به فريق Flutter. بسيط، مناسب للمشاريع الصغيرة والمتوسّطة.
flutter pub add provider2. Riverpod — خليفة Provider
نفس مؤلّف Provider، لكن أقوى وأكثر أماناً. الخيار المفضّل حالياً.
flutter pub add flutter_riverpod3. BLoC — للمشاريع الكبيرة
Business Logic Component. نمط أقوى لفصل المنطق عن الواجهة، شائع في تطبيقات الشركات.
flutter pub add flutter_blocمثال: عدّاد بـ Provider
النموذج
import 'package:flutter/foundation.dart';
class Counter extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // يُخبر المستمعين
}
}التوفير للتطبيق
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => Counter(),
child: const MyApp(),
),
);
}الاستهلاك
class CounterView extends StatelessWidget {
const CounterView({super.key});
@override
Widget build(BuildContext context) {
final counter = context.watch<Counter>();
return Column(
children: [
Text('${counter.count}'),
ElevatedButton(
onPressed: () => context.read<Counter>().increment(),
child: const Text('+1'),
),
],
);
}
}نفس المثال بـ Riverpod
// تعريف الـ provider
final counterProvider = StateProvider<int>((ref) => 0);
// التطبيق (لفّ الـ root)
void main() {
runApp(const ProviderScope(child: MyApp()));
}
// الاستهلاك
class CounterView extends ConsumerWidget {
const CounterView({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Column(
children: [
Text('$count'),
ElevatedButton(
onPressed: () => ref.read(counterProvider.notifier).state++,
child: const Text('+1'),
),
],
);
}
}نفس المثال بـ BLoC
Events و States
// الأحداث
abstract class CounterEvent {}
class Increment extends CounterEvent {}
class Decrement extends CounterEvent {}
// الـ Bloc
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<Increment>((event, emit) => emit(state + 1));
on<Decrement>((event, emit) => emit(state - 1));
}
}الاستخدام
void main() {
runApp(
BlocProvider(
create: (_) => CounterBloc(),
child: const MyApp(),
),
);
}
// الواجهة
BlocBuilder<CounterBloc, int>(
builder: (context, count) => Text('$count'),
)
// الأحداث
ElevatedButton(
onPressed: () => context.read<CounterBloc>().add(Increment()),
child: const Text('+1'),
)مقارنة
| المعيار | Provider | Riverpod | BLoC | |---------|----------|----------|------| | منحنى التعلّم | سهل | متوسّط | شديد | | Boilerplate | قليل | قليل | كثير | | أمان النوع | متوسّط | ممتاز | ممتاز | | Testing | جيّد | ممتاز | ممتاز | | مناسب لـ | مشاريع صغيرة | كل شيء | مشاريع كبيرة/فِرَق |
التوصية
- مشروع جديد: Riverpod
- مشروع فيه Provider: استمرّ بـ Provider حتى يكبر فعلاً
- شركة كبيرة + فريق: BLoC
- setState كافٍ لعدّاد بسيط — لا تعقّد الأمور بلا حاجة
أخطاء شائعة
- تعديل الـ state مباشرة بدون
notifyListeners - watch في build خارج الـ context
- وضع كل الـ state في Provider واحد ضخم — قسّم لعدّة providers صغيرة
الأسئلة الشائعة
هل أستخدم GetX؟
GetX شائع في العالم العربي لكنه غير موصى به من مجتمع Flutter الرسمي. يخلط state + routing + DI بطريقة غير Flutter-idiomatic. تجنّبه في المشاريع الجدّية.
متى أحتاج state management أصلاً؟
إن لديك أكثر من 3-4 شاشات تشترك في بيانات. لشاشة واحدة، setState كافٍ.
مقالات ذات صلة
الفرق بين Flutter و React Native: أيّهما تختار في 2026؟
مقارنة عميقة بين أشهر إطارَي عمل لتطوير الجوّال — الأداء، المجتمع، سوق العمل، وتجربة المطوّر.
كيفية نشر تطبيق Flutter على Google Play و App Store
خطوات عملية لرفع تطبيقك من جهازك إلى متاجر التطبيقات — Android أولاً ثم iOS.
بناء أول تطبيق React Native: دليل خطوة بخطوة
React Native يسمح لك ببناء تطبيقات native للـ iOS و Android باستخدام React. ابدأ من الصفر.