Нетворкінг у Flutter додатках — про просте і складне на прикладі Tide. Частина 5: REST API запити з retrofit. Про просте

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Привіт! Я Анна — експертка з мобільної розробки, GDE з Dart та Flutter, досвідчена розробниця мобільних додатків на Flutter.

Більшість додатків, чи то мобільні, чи то веб, чи десктоп, залежать від того чи іншого бекенда. Отже, імплементація комунікації з API є невід’ємною частиною реалізації додатку. У цій серії з шести частин представлені інструменти та підходи, які полегшують розробку комунікації з API у Flutter додатках, які ми використовуємо в Tide.

Обіцяю, буде корисно і цікаво розробникам будь-якого рівня!

Read in English

Якщо загубилися, почніть читати з початку.

Частини 5 і 6 цієї серії присвячені ефективній реалізації REST API запитів.

Ця частина має на меті показати базове використання пакета retrofit. Наприкінці цієї частини API виклик до Marvel Comic API з попередньої частини буде повторно імплементовано з використанням згенерованого коду.

retrofit — це пакет для генерування коду, який реалізує виклики до об’єкта dio на основі анотацій. Про мотивацію, інструкції з підключення, та основні сценарії використання читайте в документації.

В цій частині про просте:

  1. простий API запит
  2. атрибути API запитів
  3. generic API відповіді

Про складне читайте в Частині 6 цієї серії:

  1. хедери для окремих запитів
  2. хедери для більшості / всіх запитів
  3. хедери для групи запитів
  4. дії до / після запитів

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

Сподобалась стаття? Натискай «Подобається» внизу. Це допоможе автору виграти подарунок у програмі #ПишуНаDOU

👍ПодобаєтьсяСподобалось2
До обраногоВ обраному1
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Підписатись на коментарі