“数据是应用的血液,网络是连接世界的桥梁。”
在移动应用开发中,与服务器进行数据交互是必不可少的功能。无论是获取用户信息、提交表单数据,还是上传图片、下载文件,都离不开网络请求。本章将带你深入掌握Flutter中的网络编程技巧。
想象一下,你走进一家餐厅点餐的过程:
HTTP请求就是这样一个过程,只不过是应用与服务器之间的"点餐"过程。
// GET:获取数据,就像询问菜单
// POST:提交数据,就像下订单
// PUT:更新数据,就像修改订单
// DELETE:删除数据,就像取消订单
// PATCH:部分更新,就像只修改订单中的某个菜品
Flutter提供了基础的http库,但直接使用会让代码变得复杂:
import 'package:http/http.dart' as http;
import 'dart:convert';
class BasicHttpClient {
static const String baseUrl = 'https://api.example.com';
// 基础GET请求
static Future<Map<String, dynamic>> get(String endpoint) async {
try {
final response = await http.get(
Uri.parse('$baseUrl$endpoint'),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
return json.decode(response.body);
} else {
throw Exception('请求失败: ${response.statusCode}');
}
} catch (e) {
throw Exception('网络错误: $e');
}
}
}
dio库就像是一个功能强大的"网络请求管家",它帮我们处理了很多繁琐的工作:
import 'package:dio/dio.dart';
class HttpClient {
static late Dio _dio;
// 初始化dio实例
static void init() {
_dio = Dio(BaseOptions(
baseUrl: 'https://api.example.com',
connectTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 10),
sendTimeout: const Duration(seconds: 10),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
));
_setupInterceptors();
}
static Dio get dio => _dio;
}
class ApiClient {
late Dio _dio;
ApiClient() {
_dio = Dio();
_setupDio();
}
void _setupDio() {
_dio.options = BaseOptions(
baseUrl: 'https://jsonplaceholder.typicode.com',
connectTimeout: const Duration(seconds: 10),
receiveTimeout: const Duration(seconds: 10),
headers: {
'Content-Type': 'application/json',
},
);
}
// 通用请求方法
Future<T> request<T>(
String path, {
String method = 'GET',
Map<String, dynamic>? queryParameters,
dynamic data,
Map<String, dynamic>? headers,
required T Function(dynamic) fromJson,
}) async {
try {
final options = Options(
method: method,
headers: headers,
);
final response = await _dio.request(
path,
queryParameters: queryParameters,
data: data,
options: options,
);
return fromJson(response.data);
} on DioException catch (e) {
throw _handleDioError(e);
}
}
// 错误处理
String _handleDioError(DioException e) {
switch (e.type) {
case DioExceptionType.connectionTimeout:
return '连接超时,请检查网络';
case DioExceptionType.receiveTimeout:
return '接收数据超时,请重试';
case DioExceptionType.badResponse:
return '服务器错误:${e.response?.statusCode}';
case DioExceptionType.cancel:
return '请求已取消';
default:
return '网络错误:${e.message}';
}
}
}
RESTful API就像是一套标准的"服务规范":
class UserService {
final ApiClient _apiClient = ApiClient();
// 获取用户列表 (GET)
Future<List<User>> getUsers() async {
return await _apiClient.request<List<User>>(
'/users',
fromJson: (data) => (data as List)
.map((item) => User.fromJson(item))
.toList(),
);
}
// 获取单个用户 (GET)
Future<User> getUser(int id) async {
return await _apiClient.request<User>(
'/users/$id',
fromJson: (data) => User.fromJson(data),
);
}
// 创建用户 (POST)
Future<User> createUser(User user) async {
return await _apiClient.request<User>(
'/users',
method: 'POST',
data: user.toJson(),
fromJson: (data) => User.fromJson(data),
);
}
// 更新用户 (PUT)
Future<User> updateUser(int id, User user) async {
return await _apiClient.request<User>(
'/users/$id',
method: 'PUT',
data: user.toJson(),
fromJson: (data) => User.fromJson(data),
);
}
// 删除用户 (DELETE)
Future<void> deleteUser(int id) async {
await _apiClient.request<void>(
'/users/$id',
method: 'DELETE',
fromJson: (data) => null,
);
}
}
JSON序列化就像是"翻译官"的工作:
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,
});
// 从JSON创建对象(反序列化)
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'] as int,
name: json['name'] as String,
email: json['email'] as String,
avatar: json['avatar'] as String?,
);
}
// 转换为JSON(序列化)
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'email': email,
if (avatar != null) 'avatar': avatar,
};
}
String toString() {
return 'User{id: $id, name: $name, email: $email}';
}
}
首先添加依赖:
dependencies:
json_annotation: ^4.8.1
dev_dependencies:
json_serializable: ^6.7.1
build_runner: ^2.4.7
然后创建模型类:
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
()
class User {
final int id;
final String name;
final String email;
(name: 'avatar_url')
final String? avatarUrl;
(name: 'created_at')
final DateTime? createdAt;
User({
required this.id,
required this.name,
required this.email,
this.avatarUrl,
this.createdAt,
});
factory User.fromJson(Map<String, dynamic> json) =&