Нетворкінг у Flutter додатках — про просте і складне на прикладі Tide. Частина 3: HTTP клієнт та перехоплювачі запитів з dio. Про просте
Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.
Привіт! Я Анна — експертка з мобільної розробки, GDE з Dart та Flutter, досвідчена розробниця мобільних додатків на Flutter.
Більшість додатків, чи то мобільні, чи то веб, чи десктоп, залежать від того чи іншого бекенда. Отже, імплементація комунікації з API є невід’ємною частиною реалізації додатку. У цій серії з шести частин представлені інструменти та підходи, які полегшують розробку комунікації з API у Flutter додатках, які ми використовуємо в Tide.
Обіцяю, буде корисно і цікаво розробникам будь-якого рівня!
Якщо загубилися, почніть читати з початку.
Частини 3 і 4 цієї серії присвячені налаштуванню HTTP-клієнта, який використовується для завантаження даних з бекенду.
Ця частина має на меті дослідити об’єкт dio і розглянути основні налаштування. Під кінець цієї частини наша імплементація буде готова до першого API-запиту.
dio — потужний HTTP-клієнт для Dart з підтримкою численних необхідних і бонусних функцій. Про мотивацію, інструкції з підключення, та основні сценарії використання читайте в документації.
В цій частині про просте:
- dio HTTP клієнт
- перехоплювачі запитів
- перший API запит
Про складне читайте в Частині 4 цієї серії:
- імітація API
- проксі
- SSL-pinning
На момент випуску цієї серії актуальна версія Flutter 3.0.
Приклади будуються на основі коду, створеного в Частині 2, який знаходиться під тегом part-2 у Flutter Advanced Networking GitHub репозиторії.
Останні версії необхідних залежностей у файлі pubspec.yaml
:
1. dio HTTP клієнт
Dio
— це об’єкт, який використовується для отримання даних з API. Кожен запит можна налаштувати індивідуально, і до того ж існує клас BaseOptions
для загального налаштування всіх запитів:
З таким налаштуванням кожен запит матиме додатковий параметр ?parameter1=value1
і хедер {"header1":"value1"}
.
Об’єкт Dio
має .get()
, .post()
, .put()
, .patch()
, .delete()
та інші методи, які всі є обгортками над універсальним методом .request()
:
В цьому прикладі:
результуючий GET запит буде надіслано на example.com/api/get_example адресу і матиме два параметри ?parameter1=value1¶meter2=value2
і два хедери {"header1":"value1", "header2": "value2"}
. Один хедер і один параметр будуть надходити зі загального налаштування Dio
, а інша пара з хедера і параметра надходитиме із налаштування в методі .getExample()
.
На відміну від .get()
, інші методи також приймають dynamic data
параметр, який буде надіслано у запиті:
В цьому прикладі:
результуючий POST запит буде надіслано на example.com/api/post_example адресу і матиме лише параметр та хедер із загального налаштування Dio
, а також body {"id": "example_id"}
.
Зверніться до документації, щоб дізнатися більше про налаштування та методи Dio
. А ми переходимо до dio функцій, які ми використовуємо у наших Flutter проектах.
2. Перехоплювачі запитів
Dio
перехоплювач — це об’єкт із методами .onRequest()
, .onResponse()
, .onError()
, які викликаються, коли з Dio
об’єктом відбувається відповідна подія. До одного Dio
об’єкта можна додати кілька перехоплювачів.
Скажімо, існує вимога надсилати точну дату і час з кожним запитом. Можна зробити це явно, як у рядку 11
:
Як ви можете собі уявити, ця логіка буде швидко дублюватися по всьому проекту. І забути про таку вимогу тут і там не так вже й важко. Натомість це ідеальний випадок для Dio
перехоплювача:
Після приєднання до Dio
об’єкта, його метод .onRequest()
буде додавати параметр ts
до кожного запиту:
Насправді ж, Marvel Comic API висуває більш складну вимогу. Кожен запит повинен мати три параметри:
- apikey — відкритий ключ;
- ts — мітка часу (або інший довгий рядок, який може змінюватися з кожним запитом);
- hash — md5 дайджест параметра ts, приватного ключа та відкритого ключа
md5(ts+privateKey+publicKey)
.
* Свою пару приватного та відкритого ключа можна знайти на «My Developer Account» сторінці після реєстрації на developer.marvel.com.
Знову ж таки, цю вимогу можна легко задовольнити за допомогою dio
перехоплювача. Щоб зробити реалізацію трохи цікавішою та охопити деякі реальні сценарії, MarvelApiAuthInterceptor
прийматиме відкритий ключ як параметр, а приватний ключ буде асинхронно надходити зі сторонньої залежності:
Після того, як MarvelApiAuthInterceptor
додано до екземпляра Dio
, усі запити, які він робить до Marvel Comic API, є авторизованими:
Створення масиву перехоплювачів тут є навмисним. Існує певна кількість перехоплювачів, які ми зазвичай підключаємо до екземпляра Dio
у наших проектах.
3. Перший API запит
На даний момент у нас є екземпляр Dio
, налаштований з належним baseUrl
і перехоплювачем, відповідальним за виконання авторизованих запитів до API. Крім того, у попередніх частинах ми створили модель MarvelComic
та generic клас MarvelApiResponse
, який дозволяє десеріалізувати JSON відповіді від Marvel Comic API.
Це дозволяє зробити перший запит до API!
Авторизований GET запит до gateway.marvel.com:443/v1/public/comics адреси повертає список коміксів, загорнутий у generic відповідь з метаданими:
Клас MarvelComicsApi
приймає налаштований екземпляр dio
як параметр конструктора в рядку 7
. У рядку 12
у методі .getComics()
він виконує GET запит до шляху /comics
. Отриманий json
типу Map<String, dynamic>
передається в MarvelApiResponse.fromJson
конструктор у рядку 15
. Тип поля data
generic типу MarvelApiResponse
— MarvelPaginatedList
, тому конструктор MarvelPaginatedList.fromJson
викликається в рядку 16
. MarvelPaginatedList
також є generic класом з типом даних MarvelComic
, тому MarvelComic.fromJson
викликається у рядку 18
. В результаті метод .getComics()
повертає десеріалізований об’єкт MarvelApiResponse
зі списком моделей MarvelComic
.
Результат
Ми дізналися, що таке Dio
, і як використовувати його механізм перехоплювачів, а також зробили перший авторизований запит до Marvel Comic API.
Остаточна версія коду, розробленого в цій частині, знаходиться під тегом part-3 у Flutter Advanced Networking GitHub репозиторії.
Продовження у Частині 4: HTTP клієнт та перехоплювачі запитів з dio. Про складне.
Немає коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів