Kodax

Riverpod - إدارة حالة متقدمة — Flutter المتقدم

Riverpod - الجيل التالي من Provider

لماذا Riverpod؟

1. آمن من الأخطاء (Compile-time safe)

2. لا يحتاج BuildContext

3. قابل للاختبار بسهولة

4. دعم أفضل للـ async

1. الإعداد

dependencies:
  flutter_riverpod: ^2.4.0
void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

2. أنواع Providers

// Provider بسيط (قيمة ثابتة)
final greetingProvider = Provider<String>((ref) {
  return 'مرحباً بالعالم!';
});

// StateProvider (قيمة متغيرة)
final counterProvider = StateProvider<int>((ref) => 0);

// StateNotifierProvider (منطق معقد)
class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);
  
  void increment() => state++;
  void decrement() => state--;
  void reset() => state = 0;
}

final counterNotifierProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
  return CounterNotifier();
});

// FutureProvider (بيانات async)
final userProvider = FutureProvider<User>((ref) async {
  final response = await http.get(Uri.parse('https://api.example.com/user'));
  return User.fromJson(jsonDecode(response.body));
});

// StreamProvider
final messagesProvider = StreamProvider<List<Message>>((ref) {
  return chatService.messagesStream;
});

3. استخدام Providers

// مع ConsumerWidget
class CounterScreen extends ConsumerWidget {
  @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: Text('زيادة'),
        ),
      ],
    );
  }
}

// مع hooks
class CounterScreen extends HookConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    return Text('$count');
  }
}

// في StatelessWidget
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer(
      builder: (context, ref, child) {
        final count = ref.watch(counterProvider);
        return Text('$count');
      },
    );
  }
}

4. FutureProvider مع UI

final productsProvider = FutureProvider<List<Product>>((ref) async {
  final api = ref.watch(apiServiceProvider);
  return api.getProducts();
});

class ProductsScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final productsAsync = ref.watch(productsProvider);
    
    return productsAsync.when(
      loading: () => Center(child: CircularProgressIndicator()),
      error: (error, stack) => Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('خطأ: $error'),
            ElevatedButton(
              onPressed: () => ref.refresh(productsProvider),
              child: Text('إعادة المحاولة'),
            ),
          ],
        ),
      ),
      data: (products) => ListView.builder(
        itemCount: products.length,
        itemBuilder: (context, index) {
          return ProductCard(product: products[index]);
        },
      ),
    );
  }
}

5. Providers معتمدة على بعضها

final authProvider = StateProvider<User?>((ref) => null);

final userOrdersProvider = FutureProvider<List<Order>>((ref) async {
  final user = ref.watch(authProvider);
  if (user == null) return [];
  
  final api = ref.watch(apiServiceProvider);
  return api.getOrders(user.id);
});
اختبر فهمك