التعامل مع 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');
}
اختبر فهمك