Kodax

البرمجة غير المتزامنة — أساسيات Flutter

البرمجة غير المتزامنة في Dart

1. Future و async/await

// دالة غير متزامنة
Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 2));
  return 'البيانات جاهزة!';
}

// استخدام
void main() async {
  print('جاري التحميل...');
  String result = await fetchData();
  print(result);
}

// أو باستخدام then
fetchData().then((result) {
  print(result);
}).catchError((error) {
  print('خطأ: $error');
});

2. معالجة الأخطاء

Future<void> loadUser() async {
  try {
    final response = await http.get(Uri.parse(url));
    
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      print(data);
    } else {
      throw Exception('فشل التحميل');
    }
  } catch (e) {
    print('خطأ: $e');
  } finally {
    print('انتهى التحميل');
  }
}

3. FutureBuilder

class UserProfile extends StatelessWidget {
  Future<Map<String, dynamic>> fetchUser() async {
    final response = await http.get(
      Uri.parse('https://api.example.com/user/1'),
    );
    return jsonDecode(response.body);
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<Map<String, dynamic>>(
      future: fetchUser(),
      builder: (context, snapshot) {
        // جاري التحميل
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: CircularProgressIndicator());
        }
        
        // خطأ
        if (snapshot.hasError) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(Icons.error, size: 48, color: Colors.red),
                Text('حدث خطأ: ${snapshot.error}'),
                ElevatedButton(
                  onPressed: () {}, // إعادة المحاولة
                  child: Text('إعادة المحاولة'),
                ),
              ],
            ),
          );
        }
        
        // نجاح
        if (snapshot.hasData) {
          final user = snapshot.data!;
          return Column(
            children: [
              CircleAvatar(
                backgroundImage: NetworkImage(user['avatar']),
              ),
              Text(user['name']),
              Text(user['email']),
            ],
          );
        }
        
        return Container();
      },
    );
  }
}

4. Stream و StreamBuilder

// إنشاء Stream
Stream<int> countStream(int max) async* {
  for (int i = 1; i <= max; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

// استخدام مع StreamBuilder
class CounterScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<int>(
      stream: countStream(10),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Text(
            '${snapshot.data}',
            style: TextStyle(fontSize: 48),
          );
        }
        return CircularProgressIndicator();
      },
    );
  }
}

// StreamController
class ChatService {
  final _controller = StreamController<Message>.broadcast();
  
  Stream<Message> get messages => _controller.stream;
  
  void sendMessage(Message msg) {
    _controller.add(msg);
  }
  
  void dispose() {
    _controller.close();
  }
}

5. مثال تطبيقي: تحميل قائمة منتجات

class ProductsScreen extends StatefulWidget {
  @override
  _ProductsScreenState createState() => _ProductsScreenState();
}

class _ProductsScreenState extends State<ProductsScreen> {
  late Future<List<Product>> _productsFuture;

  @override
  void initState() {
    super.initState();
    _productsFuture = _fetchProducts();
  }

  Future<List<Product>> _fetchProducts() async {
    final response = await http.get(
      Uri.parse('https://api.example.com/products'),
    );
    
    if (response.statusCode == 200) {
      final List<dynamic> data = jsonDecode(response.body);
      return data.map((json) => Product.fromJson(json)).toList();
    } else {
      throw Exception('فشل تحميل المنتجات');
    }
  }

  void _refresh() {
    setState(() {
      _productsFuture = _fetchProducts();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('المنتجات'),
        actions: [
          IconButton(
            icon: Icon(Icons.refresh),
            onPressed: _refresh,
          ),
        ],
      ),
      body: FutureBuilder<List<Product>>(
        future: _productsFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          }

          if (snapshot.hasError) {
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.error_outline, size: 48, color: Colors.red),
                  SizedBox(height: 16),
                  Text('حدث خطأ في التحميل'),
                  SizedBox(height: 16),
                  ElevatedButton(
                    onPressed: _refresh,
                    child: Text('إعادة المحاولة'),
                  ),
                ],
              ),
            );
          }

          final products = snapshot.data!;
          
          if (products.isEmpty) {
            return Center(child: Text('لا توجد منتجات'));
          }

          return RefreshIndicator(
            onRefresh: () async {
              _refresh();
            },
            child: ListView.builder(
              itemCount: products.length,
              itemBuilder: (context, index) {
                final product = products[index];
                return ProductCard(product: product);
              },
            ),
          );
        },
      ),
    );
  }
}

// Model
class Product {
  final int id;
  final String name;
  final double price;
  final String image;

  Product({
    required this.id,
    required this.name,
    required this.price,
    required this.image,
  });

  factory Product.fromJson(Map<String, dynamic> json) {
    return Product(
      id: json['id'],
      name: json['name'],
      price: json['price'].toDouble(),
      image: json['image'],
    );
  }
}
اختبر فهمك