Kodax

التعامل مع APIs — أساسيات Flutter

التعامل مع APIs في Flutter

1. إعداد http package

# pubspec.yaml
dependencies:
  http: ^1.1.0
import 'package:http/http.dart' as http;
import 'dart:convert';

2. GET Request

Future<List<User>> fetchUsers() async {
  final response = await http.get(
    Uri.parse('https://jsonplaceholder.typicode.com/users'),
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR_TOKEN',
    },
  );

  if (response.statusCode == 200) {
    final List<dynamic> data = jsonDecode(response.body);
    return data.map((json) => User.fromJson(json)).toList();
  } else {
    throw Exception('Failed to load users');
  }
}

3. POST Request

Future<User> createUser(String name, String email) async {
  final response = await http.post(
    Uri.parse('https://api.example.com/users'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode({
      'name': name,
      'email': email,
    }),
  );

  if (response.statusCode == 201) {
    return User.fromJson(jsonDecode(response.body));
  } else {
    throw Exception('Failed to create user');
  }
}

4. PUT و DELETE

// PUT - تحديث
Future<User> updateUser(int id, Map<String, dynamic> data) async {
  final response = await http.put(
    Uri.parse('https://api.example.com/users/$id'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode(data),
  );

  if (response.statusCode == 200) {
    return User.fromJson(jsonDecode(response.body));
  } else {
    throw Exception('Failed to update user');
  }
}

// DELETE - حذف
Future<void> deleteUser(int id) async {
  final response = await http.delete(
    Uri.parse('https://api.example.com/users/$id'),
  );

  if (response.statusCode != 200) {
    throw Exception('Failed to delete user');
  }
}

5. API Service Class

class ApiService {
  static const baseUrl = 'https://api.example.com';
  
  static Future<Map<String, String>> _getHeaders() async {
    final token = await SecureStorage.getToken();
    return {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer $token',
    };
  }

  // GET
  static Future<T> get<T>(
    String endpoint,
    T Function(dynamic) fromJson,
  ) async {
    final response = await http.get(
      Uri.parse('$baseUrl$endpoint'),
      headers: await _getHeaders(),
    );
    
    if (response.statusCode == 200) {
      return fromJson(jsonDecode(response.body));
    } else {
      throw ApiException(response.statusCode, response.body);
    }
  }

  // POST
  static Future<T> post<T>(
    String endpoint,
    Map<String, dynamic> body,
    T Function(dynamic) fromJson,
  ) async {
    final response = await http.post(
      Uri.parse('$baseUrl$endpoint'),
      headers: await _getHeaders(),
      body: jsonEncode(body),
    );
    
    if (response.statusCode == 201 || response.statusCode == 200) {
      return fromJson(jsonDecode(response.body));
    } else {
      throw ApiException(response.statusCode, response.body);
    }
  }
}

// استثناء مخصص
class ApiException implements Exception {
  final int statusCode;
  final String message;
  
  ApiException(this.statusCode, this.message);
  
  @override
  String toString() => 'ApiException: $statusCode - $message';
}

// الاستخدام
final users = await ApiService.get<List<User>>(
  '/users',
  (json) => (json as List).map((e) => User.fromJson(e)).toList(),
);

6. Dio (أقوى وأسهل)

dependencies:
  dio: ^5.3.0
import 'package:dio/dio.dart';

class DioClient {
  late Dio _dio;

  DioClient() {
    _dio = Dio(BaseOptions(
      baseUrl: 'https://api.example.com',
      connectTimeout: Duration(seconds: 10),
      receiveTimeout: Duration(seconds: 10),
      headers: {'Content-Type': 'application/json'},
    ));

    // Interceptors
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) async {
        final token = await getToken();
        options.headers['Authorization'] = 'Bearer $token';
        return handler.next(options);
      },
      onResponse: (response, handler) {
        return handler.next(response);
      },
      onError: (error, handler) {
        if (error.response?.statusCode == 401) {
          // Token expired - refresh or logout
        }
        return handler.next(error);
      },
    ));
  }

  Future<List<User>> getUsers() async {
    final response = await _dio.get('/users');
    return (response.data as List)
        .map((json) => User.fromJson(json))
        .toList();
  }

  Future<User> createUser(Map<String, dynamic> data) async {
    final response = await _dio.post('/users', data: data);
    return User.fromJson(response.data);
  }

  // رفع ملف
  Future<String> uploadImage(File file) async {
    final formData = FormData.fromMap({
      'file': await MultipartFile.fromFile(file.path),
    });
    final response = await _dio.post('/upload', data: formData);
    return response.data['url'];
  }
}

7. مثال كامل: Repository Pattern

// models/user.dart
class User {
  final int id;
  final String name;
  final String email;
  final String? avatar;

  User({
    required this.id,
    required this.name,
    required this.email,
    this.avatar,
  });

  factory User.fromJson(Map<String, dynamic> json) {
    return User(
      id: json['id'],
      name: json['name'],
      email: json['email'],
      avatar: json['avatar'],
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'email': email,
      'avatar': avatar,
    };
  }
}

// repositories/user_repository.dart
class UserRepository {
  final DioClient _client;

  UserRepository(this._client);

  Future<List<User>> getAll() => _client.getUsers();
  
  Future<User> getById(int id) async {
    final response = await _client.dio.get('/users/$id');
    return User.fromJson(response.data);
  }
  
  Future<User> create(User user) => _client.createUser(user.toJson());
  
  Future<User> update(User user) async {
    final response = await _client.dio.put(
      '/users/${user.id}',
      data: user.toJson(),
    );
    return User.fromJson(response.data);
  }
  
  Future<void> delete(int id) => _client.dio.delete('/users/$id');
}
اختبر فهمك