← Назад к вопросам
Как выполнять сетевые запросы во Flutter?
1.0 Junior🔥 252 комментариев
#Работа с сетью
Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Сетевые запросы во Flutter
Встроенный пакет http
http — это встроенный пакет Flutter для выполнения HTTP запросов. Это простой и лёгкий способ:
import "package:http/http.dart" as http;
// GET запрос
Future<void> fetchUserData() async {
try {
final response = await http.get(
Uri.parse("https://api.example.com/users/1"),
headers: {
"Authorization": "Bearer token",
"Content-Type": "application/json",
},
);
if (response.statusCode == 200) {
print(response.body);
} else {
print("Error: ${response.statusCode}");
}
} catch (e) {
print("Error: $e");
}
}
// POST запрос
Future<void> createUser() async {
final response = await http.post(
Uri.parse("https://api.example.com/users"),
headers: {"Content-Type": "application/json"},
body: jsonEncode({
"name": "John",
"email": "john@example.com",
}),
);
if (response.statusCode == 201) {
print("User created");
}
}
// DELETE запрос
Future<void> deleteUser(String id) async {
final response = await http.delete(
Uri.parse("https://api.example.com/users/$id"),
);
print(response.statusCode);
}
Dio — более мощная альтернатива
Dio имеет больше функций: перехватчики (interceptors), таймауты, отмену запросов:
import "package:dio/dio.dart";
final dio = Dio(
BaseOptions(
baseUrl: "https://api.example.com",
connectTimeout: Duration(seconds: 5),
receiveTimeout: Duration(seconds: 3),
headers: {"Authorization": "Bearer token"},
),
);
// GET запрос
Future<void> fetchUsers() async {
try {
final response = await dio.get("/users");
print(response.data); // Автоматически парсит JSON
} on DioException catch (e) {
print("Error: ${e.message}");
}
}
// POST с параметрами
Future<void> createUser(String name, String email) async {
final response = await dio.post(
"/users",
data: {"name": name, "email": email},
);
print(response.data);
}
// Отмена запроса
final cancelToken = CancelToken();
await dio.get("/users", cancelToken: cancelToken);
cancelToken.cancel("Request cancelled");
Перехватчики (Interceptors) в Dio
dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options, handler) {
// Модифицировать запрос перед отправкой
print("Sending request to: ${options.path}");
return handler.next(options);
},
onResponse: (response, handler) {
// Обработать ответ
print("Response: ${response.statusCode}");
return handler.next(response);
},
onError: (DioException e, handler) {
// Обработать ошибку
print("Error: ${e.message}");
return handler.next(e);
},
),
);
Работа с JSON
import "dart:convert";
class User {
final int id;
final String name;
final String email;
User({required this.id, required this.name, required this.email});
// Из JSON
factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json["id"],
name: json["name"],
email: json["email"],
);
}
// В JSON
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"email": email,
};
}
// Использование
Future<User> fetchUser(int id) async {
final response = await http.get(
Uri.parse("https://api.example.com/users/$id"),
);
if (response.statusCode == 200) {
return User.fromJson(jsonDecode(response.body));
} else {
throw Exception("Failed to load user");
}
}
// Список объектов
Future<List<User>> fetchUsers() async {
final response = await http.get(
Uri.parse("https://api.example.com/users"),
);
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");
}
}
Интеграция с BLoC
class UserBloc extends Bloc<UserEvent, UserState> {
final ApiService apiService;
UserBloc(this.apiService) : super(UserInitial()) {
on<FetchUserEvent>(_onFetchUser);
}
Future<void> _onFetchUser(
FetchUserEvent event,
Emitter<UserState> emit,
) async {
emit(UserLoading());
try {
final user = await apiService.fetchUser(event.userId);
emit(UserLoaded(user));
} catch (e) {
emit(UserError(e.toString()));
}
}
}
// В UI
class UserPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
if (state is UserLoading) {
return CircularProgressIndicator();
} else if (state is UserLoaded) {
return Text(state.user.name);
} else if (state is UserError) {
return Text("Error: ${state.message}");
}
return SizedBox();
},
);
}
}
Авторизация и заголовки
class ApiService {
final Dio dio;
ApiService(this.dio) {
_setupInterceptors();
}
void _setupInterceptors() {
dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options, handler) async {
// Добавить токен к каждому запросу
final token = await _getToken();
options.headers["Authorization"] = "Bearer $token";
return handler.next(options);
},
onError: (DioException e, handler) async {
// Обновить токен при ошибке 401
if (e.response?.statusCode == 401) {
try {
await _refreshToken();
return handler.resolve(
await _retry(e.requestOptions),
);
} catch (_) {
return handler.next(e);
}
}
return handler.next(e);
},
),
);
}
Future<String> _getToken() async {
// Получить токен из SharedPreferences
return "token";
}
Future<void> _refreshToken() async {
// Обновить токен на сервере
}
Future<Response<dynamic>> _retry(RequestOptions requestOptions) async {
final options = Options(
method: requestOptions.method,
headers: requestOptions.headers,
);
return dio.request<dynamic>(
requestOptions.path,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters,
options: options,
);
}
}
REST API рекомендации
- GET — получение данных
- POST — создание ресурса
- PUT/PATCH — обновление ресурса
- DELETE — удаление ресурса
Обработка ошибок
Future<void> safeApiCall() async {
try {
final response = await dio.get("/users");
// Успех
} on DioException catch (e) {
if (e.type == DioExceptionType.connectionTimeout) {
print("Connection timeout");
} else if (e.type == DioExceptionType.receiveTimeout) {
print("Receive timeout");
} else if (e.response?.statusCode == 404) {
print("Not found");
} else if (e.response?.statusCode == 500) {
print("Server error");
}
} catch (e) {
print("Unknown error: $e");
}
}
Итог
- http — для простых GET запросов
- Dio — для сложных приложений с авторизацией и перехватчиками
- Всегда типизируйте JSON-ответы (User, Post и т.д.)
- Обрабатывайте ошибки и таймауты
- Интегрируйте с BLoC для управления состоянием