Http

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:second_app/contact.dart';
import 'package:second_app/products.dart';
import 'colors.dart';
import 'package:http/http.dart';

class HomaPage extends StatefulWidget {
  HomaPage({super.key});
  @override
  State<HomaPage> createState() => _HomaPageState();
}

class _HomaPageState extends State<HomaPage> {
  final userNameController = TextEditingController();
  final formKey = GlobalKey<FormState>();
  String? userName;
  List data = [];
  bool loading = true;

  getData() async {
   
    var response = await get(Uri.parse("https://fakestoreapi.com/products"));
    var resBody = jsonDecode(response.body);

    data.clear(); // عشان ما يتكرر التحميل
    data.addAll(resBody);
    loading = false;
    // setState(() {});
  }

  @override
  void initState() {
    getData();
    super.initState();
  }

  @override
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Fake Store")),
      drawer: Drawer(),
      body: Column(
        children: [
          if (loading) Center(child: Text("جاري التحميل")),

          
          Expanded(
            child: GridView.builder(
              padding: EdgeInsets.all(10),
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2, // عدد الأعمدة
                crossAxisSpacing: 10,
                mainAxisSpacing: 10,
                childAspectRatio: 0.7,
              ),
              itemCount: data.length,
              itemBuilder: (context, i) {
                final item = data[i];
                return Card(
                  elevation: 2,
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(7),
                  ),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      // الصورة
                      Expanded(
                        child: ClipRRect(
                          borderRadius: BorderRadius.vertical(
                            top: Radius.circular(8),
                          ),
                          child: Image.network(
                            item['image'],
                            width: double.infinity,
                            fit: BoxFit.cover,
                          ),
                        ),
                      ),

                      // النصوص
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              item['title'],
                              maxLines: 2,
                              overflow: TextOverflow.ellipsis,
                              style: TextStyle(
                                fontWeight: FontWeight.bold,
                                color: Colors.blue,
                              ),
                            ),
                            Text(
                              item['description'],
                              maxLines: 2,
                              overflow: TextOverflow.ellipsis,
                              style: TextStyle(),
                            ),
                            SizedBox(height: 4),
                            Text(
                              "\$${item['price']}",
                              style: TextStyle(
                                fontSize: 16,
                                fontWeight: FontWeight.w600,
                              ),
                            ),
                          ],
                        ),
                      ),
                    ],
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}
Dart
شرح الدالة getData()
getData() async {
Dart
  • async: تعني أن الدالة غير متزامنة وتُرجِع Future.
  • هذا يسمح لك باستخدام await بداخلها لتنفيذ عمليات تستغرق وقتًا (مثل طلبات الشبكة) بدون تجميد واجهة المستخدم.
  var response = await get(Uri.parse("https://fakestoreapi.com/products"));
Dart
  • Uri.parse(…): يحوّل النص إلى كائن Uri صالح لطلب HTTP.
  • get(…): استدعاء HTTP GET (عادة من حزمة http).
  • await: يوقف تنفيذ الدالة هنا حتى يعود الرد من الخادم.
  • response: يحتوي على كود الحالة (statusCode) والرأس (headers) والنص (body) للرد.
  var resBody = jsonDecode(response.body);
Dart
  • jsonDecode: يفك ترميز الـ JSON النصي إلى كائنات Dart (غالبًا List<dynamic> أو Map<String, dynamic> حسب البيانات).
  • هنا الـ API يُرجع قائمة منتجات، فـ resBody ستكون غالبًا List<dynamic> من العناصر (كل عنصر Map<String, dynamic>).
  data.clear(); // عشان ما يتكرر التحميل
Dart
  • يفّضي القائمة data قبل إضافة البيانات الجديدة لتجنّب التكرار في كل مرّة تُستدعى فيها الدالة.
  data.addAll(resBody);
Dart
  • يضيف كل عناصر resBody إلى data دفعة واحدة.
  • مهم: تأكد أن نوع data متوافق (مثلاً List<Map<String, dynamic>> أو List<dynamic>).
  loading = false;
Dart
  • يحدّث فلاغ التحميل ليشير إلى أن البيانات أصبحت جاهزة.
 setState(() {});
Dart
دورة حياة الـ Widget — initState
@override
void initState() {
  super.initState();
  getData();
}
Dart
  • initState: تُستدعى مرّة واحدة عند إنشاء حالة الـ StatefulWidget.
  • المكان الصحيح لبدء تحميل البيانات الأولية.
  • ملاحظة مهمة: من الأفضل استدعاء super.initState() أولاً (وإن كانت تعمل غالبًا لو أخّرتها، لكن تنصيح Flutter الرسمي يضعها في البداية).
  • استدعاء getData() بدون await هنا صحيح؛ لأن initState ليست async.
  • الدالة ستبدأ التحميل في الخلفية، وحين تنتهي ينبغي أن تُحدّث الحالة (عادةً عبر setState).
👇 التوضيح بالتفصيل:
🔹 الكلاس Uri
  • هو كلاس مدمج في Dart (وليس Flutter ولا http).
  • يُستخدم لإنشاء وتحليل روابط الإنترنت (Uniform Resource Identifier).
  • مثلاً:
  • var uri = Uri.parse("https://example.com/products?id=1"); print(uri.scheme); // https print(uri.host); // example.com print(uri.path); // /products print(uri.query); // id=1
🔹 الدالة Uri.parse(String url)
  • تحوّل النص (String) إلى كائن من نوع Uri.
  • هذا الكائن يُستخدم بواسطة مكتبة http أو أي مكتبة أخرى لإرسال الطلبات.

🔹 مكتبة http

  • مكتبة خارجية (من pub.dev).
  • الدالة get(...) الخاصة بها تتوقّع كائنًا من نوع Uri كمعامل.
  • لذلك تكتب: var response = await get(Uri.parse("https://fakestoreapi.com/products"));
  • وليس: var response = await get("https://fakestoreapi.com/products"); // ❌ خطأ لأن get() يريد Uri وليس String.

📘 خلاصة:

الكودينتمي إلىوظيفته
Uri.parse(...)مكتبة Dart الأساسية (dart:core)تحويل النص إلى كائن URI
get()مكتبة http (من pub.dev)إرسال طلب HTTP GET باستخدام الـ URI

🔹 السطر:

var resBody = jsonDecode(response.body);
Dart
📍 المعنى العام:

يفك ترميز (decode) النص بصيغة JSON القادم من الخادم (الـ API) ويحوّله إلى كائنات Dart (قوائم أو خرائط).

📦 تفصيل كل جزء:

1️⃣ response

  • هذا هو الكائن الذي رجع من السطر: var response = await get(Uri.parse("https://fakestoreapi.com/products"));
  • يحتوي على بيانات الرد من الخادم.
  • أهم الخصائص فيه:
    • response.statusCode → رقم حالة الطلب (200 = ناجح، 404 = غير موجود…)
    • response.bodyالنص الكامل الذي أرسله السيرفر (عادة يكون بصيغة JSON).

2️⃣ response.body

  • هي نص (String) يحتوي على البيانات الخام من الخادم.
  • مثال فعلي من https://fakestoreapi.com/products: [ { "id": 1, "title": "Fjallraven - Foldsack No. 1 Backpack", "price": 109.95, "category": "men's clothing", "image": "https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg" }, ... ]
  • هذا مجرد نص JSON، ليس كائنًا يمكن التعامل معه مباشرة في Dart.

3️⃣ jsonDecode(...)

  • دالة من مكتبة dart:convert (مكتبة رسمية من Dart).
  • تُحوِّل النص JSON إلى كائنات Dart:
    • إذا كان JSON قائمة ([...]) → تتحول إلى List<dynamic>
    • إذا كان JSON كائنًا ({...}) → يتحول إلى Map<String, dynamic>

📦 لذلك:

import 'dart:convert';
Dart

يجب أن يكون موجودًا في أعلى الملف.

4️⃣ النتيجة:

في مثالنا، السيرفر يُرجع قائمة من المنتجات، لذا:

var resBody = jsonDecode(response.body);
Dart

ينتج:

resBody is List<dynamic>;
resBody[0] is Map<String, dynamic>;
Dart

أي:

  • resBody = قائمة فيها عناصر (كل عنصر منتج).
  • كل منتج عبارة عن خريطة (Map) تحتوي على مفاتيح وقيم مثل "title", "price", "image", إلخ.
🔹 مثال عملي:
var response = await get(Uri.parse("https://fakestoreapi.com/products"));
var resBody = jsonDecode(response.body);

print(resBody.runtimeType); // List<dynamic>
print(resBody[0]['title']); // يطبع عنوان أول منتج
print(resBody[0]['price']); // يطبع السعر
Dart

⚠️ ملاحظات مهمة:

  1. تأكّد من نجاح الطلب قبل محاولة jsonDecode
if (response.statusCode == 200) {
  var resBody = jsonDecode(response.body);
} else {
  print('حدث خطأ في التحميل: ${response.statusCode}');
}
Dart
  1. لو حاولت تفكيك نص ليس JSON صالح، سترمي jsonDecode خطأ (FormatException).
  2. استخدم أنواع صريحة إذا عرفت نوع البيانات:
List<Map<String, dynamic>> resBody = List<Map<String, dynamic>>.from(jsonDecode(response.body));
Dart

🧠 خلاصة الجدول:

العنصرمن أين؟نوعهوظيفته
responseمن مكتبة httpResponseنتيجة الطلب من السيرفر
response.bodyخاصية في ResponseStringالنص (عادة JSON) من الخادم
jsonDecode()من مكتبة dart:convertFunctionتحويل JSON النصي إلى كائنات Dart
resBodyمتغيركList أو Mapالبيانات الجاهزة للاستخدام في الكود