Нетворкінг у 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. Про складне.
Немає коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів