Нетворкінг у Flutter додатках — про просте і складне на прикладі Tide. Частина 5: REST API запити з retrofit. Про просте
Привіт! Я Анна — експертка з мобільної розробки, GDE з Dart та Flutter, досвідчена розробниця мобільних додатків на Flutter.
Більшість додатків, чи то мобільні, чи то веб, чи десктоп, залежать від того чи іншого бекенда. Отже, імплементація комунікації з API є невід’ємною частиною реалізації додатку. У цій серії з шести частин представлені інструменти та підходи, які полегшують розробку комунікації з API у Flutter додатках, які ми використовуємо в Tide.
Обіцяю, буде корисно і цікаво розробникам будь-якого рівня!

Якщо загубилися, почніть читати з початку.
Частини 5 і 6 цієї серії присвячені ефективній реалізації REST API запитів.
Ця частина має на меті показати базове використання пакета retrofit. Наприкінці цієї частини API виклик до Marvel Comic API з попередньої частини буде повторно імплементовано з використанням згенерованого коду.
retrofit — це пакет для генерування коду, який реалізує виклики до об’єкта dio на основі анотацій. Про мотивацію, інструкції з підключення, та основні сценарії використання читайте в документації.
В цій частині про просте:
- простий API запит
- атрибути API запитів
- generic API відповіді
Про складне читайте в Частині 6 цієї серії:
- хедери для окремих запитів
- хедери для більшості / всіх запитів
- хедери для групи запитів
- дії до / після запитів
На момент випуску цієї серії актуальна версія Flutter 3.0.
Приклади будуються на основі коду, створеного в Частині 4, який знаходиться під тегом part-4 у Flutter Advanced Networking GitHub репозиторії.
Останні версії необхідних залежностей у файлі pubspec.yaml:

1. Простий API запит
Розляньмо приклад:
Метод .getExample() складається з чотирьох рядків переважно шаблонного коду, тоді як змістовною інформацією є лише частина шляху /get_example у рядку 11 і тип результату ExampleResponse у рядку 13. Чи не було б круто вказувати лише адресу запиту, параметри та очікуваний тип відповіді, а все інше залишити механізму генерування коду? Ось для чого нам пакет retrofit.
Нова реалізація ExampleApi:
Атрибут @RestApi у рядку 9 анотує весь абстрактний клас ExampleApi у рядку 10. Фабричний конструктор приймає екземпляр dio і повертає конструктор _ExampleApi, який буде згенеровано. Метод .getExample() у рядку 14 оголошує свій тип результату ExampleResponse і анотується атрибутом @GET у рядку 13, що приймає частину адреси запиту /get_example. Анотація part в рядку 7 інформує про назву файлу для згенерованого коду.
Згенерований файл .g.dart містить:
Згенерований клас _ExampleApi реалізує абстрактний клас ExampleApi, оголошений раніше. По суті, код дуже схожий на те, що було написано у попередній реалізації ExampleApi. Об’єкт dio, переданий у конструктор у рядку 6, викликається з типом даних Map<String, dynamic> у рядку 18 через GET запит у рядку 20 до шляху /get_example у рядку 21. Відповідь десеріалізується у ExampleResponse через ExampleResponse.fromJson() метод у рядку 23.

2. Атрибути API запитів
Ось ще один приклад, що демонструє більше атрибутів з retrofit:
Атрибут @RestApi у рядку 5 тепер приймає параметр baseUrl. Метод .postExample() у рядку 10 має тип запиту POST, і його шлях містить id, який передається як параметр методу .postExample() з атрибутом @Path у рядку 11. Метод .postExample() надсилає дані типу Map<String, dynamic>, які анотовано атрибутом @Body у рядку 12. Тип результату .postExample() вказано в оголошенні методу в рядку 10. Метод .putExample() дуже схожий, але він виконує PUT запит. Він також приймає @Path параметр id у рядку 17, але додатково має параметр @Query з назвою apiKey у рядку 18. Його @Body у рядку 19 має кастомний тип ExampleBody. I нарешті, метод .deleteExample(), оголошений у рядку 23, має лише @Path параметр id і виконує DELETE запит.
Згенерований файл .g.dart містить:
Базовий URL, типи запитів, шляхи та параметри запитів були скопійовані з абстрактної декларації класу ExampleApi до згенерованої реалізації.
retrofit дозволяє вказувати лише важливу інформацію про кожен запит і генерує весь шаблонний код. Зверніться до документації, щоб дізнатися про більше функцій.

3. Generic API відповіді
Нагадаю, як в попередній частині ми реалізували перший виклик до Marvel Comic API:
API повертає дані, загорнуті в generic об’єкт відповіді, що містить метадані запиту: MarvelApiResponse<T> з полем final T data. Та retrofit також охоплює цей випадок.
Для нової реалізації MarvelComicsApi:
згенеровано .g.dart файл, що містить:
Досить схоже на те, що було раніше написано вручну, чи не так? Згенерований код містить виклик MarvelApiResponse<...>.fromJson() у рядку 16 із двома параметрами, як це і має бути. Більше того, внутрішній тип MarvelApiResponse обʼєкта також є generic, і MarvelPaginatedList<...>.fromJson() також викликається з двома параметрами в рядку 18. Нарешті, внутрішнім типом MarvelPaginatedList є MarvelComic, тому MarvelComic.fromJson() викликається у рядку 20.

Результат
Тепер для виконання запитів до Marvel Comic API ми маємо реалізацію MarvelApi на основі retrofit.
Остаточна версія коду, розробленого в цій частині, знаходиться під тегом part-5 у Flutter Advanced Networking GitHub репозиторії.
Продовження у Частині 6: REST API запити з retrofit. Про складне.
Немає коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів