إدارة الحالة مع Provider — أساسيات Flutter
إدارة الحالة مع Provider
1. إعداد Provider
dependencies:
provider: ^6.0.5
2. ChangeNotifier
import 'package:flutter/foundation.dart';
class CounterProvider extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // إعلام المستمعين
}
void decrement() {
_count--;
notifyListeners();
}
void reset() {
_count = 0;
notifyListeners();
}
}
3. تسجيل Provider
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CounterProvider()),
ChangeNotifierProvider(create: (_) => ThemeProvider()),
ChangeNotifierProvider(create: (_) => AuthProvider()),
],
child: MyApp(),
),
);
}
4. استخدام Provider
// الطريقة 1: context.watch (يُعاد البناء عند التغيير)
class CounterScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = context.watch<CounterProvider>();
return Column(
children: [
Text('${counter.count}', style: TextStyle(fontSize: 48)),
ElevatedButton(
onPressed: counter.increment,
child: Text('زيادة'),
),
],
);
}
}
// الطريقة 2: context.read (لا يُعاد البناء)
ElevatedButton(
onPressed: () => context.read<CounterProvider>().increment(),
child: Text('زيادة'),
)
// الطريقة 3: Consumer (للتحكم الدقيق)
Consumer<CounterProvider>(
builder: (context, counter, child) {
return Text('${counter.count}');
},
)
// الطريقة 4: Selector (للأداء الأفضل)
Selector<CounterProvider, int>(
selector: (_, provider) => provider.count,
builder: (context, count, child) {
return Text('$count');
},
)
5. مثال: عربة التسوق
// models/cart_item.dart
class CartItem {
final String id;
final String name;
final double price;
int quantity;
CartItem({
required this.id,
required this.name,
required this.price,
this.quantity = 1,
});
double get total => price * quantity;
}
// providers/cart_provider.dart
class CartProvider extends ChangeNotifier {
final Map<String, CartItem> _items = {};
Map<String, CartItem> get items => {..._items};
int get itemCount => _items.values.fold(0, (sum, item) => sum + item.quantity);
double get totalPrice => _items.values.fold(0, (sum, item) => sum + item.total);
void addItem(String id, String name, double price) {
if (_items.containsKey(id)) {
_items[id]!.quantity++;
} else {
_items[id] = CartItem(id: id, name: name, price: price);
}
notifyListeners();
}
void removeItem(String id) {
_items.remove(id);
notifyListeners();
}
void decreaseQuantity(String id) {
if (_items.containsKey(id)) {
if (_items[id]!.quantity > 1) {
_items[id]!.quantity--;
} else {
_items.remove(id);
}
notifyListeners();
}
}
void clear() {
_items.clear();
notifyListeners();
}
}
// screens/cart_screen.dart
class CartScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('العربة'),
actions: [
IconButton(
icon: Icon(Icons.delete_sweep),
onPressed: () => context.read<CartProvider>().clear(),
),
],
),
body: Consumer<CartProvider>(
builder: (context, cart, child) {
if (cart.items.isEmpty) {
return Center(child: Text('العربة فارغة'));
}
return Column(
children: [
Expanded(
child: ListView.builder(
itemCount: cart.items.length,
itemBuilder: (context, index) {
final item = cart.items.values.toList()[index];
return ListTile(
title: Text(item.name),
subtitle: Text('${item.price} × ${item.quantity}'),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.remove),
onPressed: () => cart.decreaseQuantity(item.id),
),
Text('${item.quantity}'),
IconButton(
icon: Icon(Icons.add),
onPressed: () => cart.addItem(item.id, item.name, item.price),
),
],
),
);
},
),
),
Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [BoxShadow(blurRadius: 10, color: Colors.black12)],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('المجموع', style: TextStyle(color: Colors.grey)),
Text(
'${cart.totalPrice.toStringAsFixed(0)} د.ع',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
],
),
ElevatedButton(
onPressed: () {},
child: Text('إتمام الشراء'),
),
],
),
),
],
);
},
),
);
}
}
// widget أيقونة العربة
class CartIcon extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Stack(
children: [
IconButton(
icon: Icon(Icons.shopping_cart),
onPressed: () => Navigator.pushNamed(context, '/cart'),
),
Positioned(
right: 0,
top: 0,
child: Consumer<CartProvider>(
builder: (context, cart, child) {
if (cart.itemCount == 0) return SizedBox.shrink();
return Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Text(
'${cart.itemCount}',
style: TextStyle(color: Colors.white, fontSize: 12),
),
);
},
),
),
],
);
}
}
اختبر فهمك