Ответ
Да, я использовал пакет retrofit в сочетании с dio и retrofit_generator для декларативного описания API-клиентов в Flutter-приложениях. Этот подход позволяет сгенерировать весь шаблонный HTTP-код, сосредоточившись только на определении endpoints и их параметров.
Как я настраиваю проект:
В pubspec.yaml добавляю зависимости:
dependencies:
dio: ^5.0.0
retrofit: ^4.0.0
dev_dependencies:
retrofit_generator: ^4.0.0
build_runner: ^2.0.0
Пример декларативного API-сервиса для работы с постами:
import 'package:dio/dio.dart';
import 'package:retrofit/retrofit.dart';
import 'package:json_annotation/json_annotation.dart';
import 'models/post.dart'; // Модель, созданная с json_serializable
part 'api_service.g.dart'; // Файл для кодогенерации
@RestApi(baseUrl: "https://jsonplaceholder.typicode.com")
abstract class ApiService {
factory ApiService(Dio dio, {String baseUrl}) = _ApiService;
// GET запрос с path-параметром
@GET("/posts/{id}")
Future<Post> getPost(@Path("id") int id);
// GET запрос с query-параметрами и кастомным header
@GET("/posts")
@Headers({"Custom-Header": "my-value"})
Future<List<Post>> getPostsForUser(
@Query("userId") int userId,
@Query("_sort") String sortBy, // Например, "id"
);
// POST запрос с телом в формате JSON
@POST("/posts")
Future<Post> createPost(@Body() Post post);
// Multipart запрос для загрузки файла
@POST("/upload")
@MultiPart()
Future<void> uploadFile(@Part() File file, @Part() String description);
}
Инициализация и использование в коде:
void main() {
// 1. Создаём Dio-клиент с настройками
final dio = Dio();
dio.options.connectTimeout = Duration(seconds: 30);
dio.interceptors.add(LogInterceptor()); // Логирование запросов
// 2. Создаём экземпляр сгенерированного API-клиента
final apiService = ApiService(dio);
// 3. Используем как обычный асинхронный метод
runApp(MyApp(apiService: apiService));
}
// В бизнес-логике или ViewModel
Future<void> fetchData() async {
try {
final post = await apiService.getPost(1);
final userPosts = await apiService.getPostsForUser(5, "id");
// Обработка данных...
} on DioException catch (e) {
// Обработка ошибок сети/сервера
print('Error: ${e.response?.statusCode}');
}
}
Запуск генерации: После определения абстрактного класса запускаю:
flutter pub run build_runner build
Генератор создаст класс _ApiService в файле api_service.g.dart, который содержит всю реализацию HTTP-вызовов с использованием Dio.
Преимущества, которые я получил:
- Чистота и читаемость: Интерфейс API становится само-документируемым.
- Безопасность типов: Параметры и возвращаемые значения строго типизированы.
- Снижение ошибок: Уходит ручное формирование URL, query-параметров и headers.
- Мощь Dio: Сохраняются все возможности Dio (интерцепторы, трансформеры, отмена запросов).
Ограничения: Для очень нестандартных запросов иногда проще использовать чистый Dio, но в 95% случаев Retrofit полностью покрывает потребности.