Lesson 7

Урок 7. HTTP и HTTPS, сетевые запросы в Dart и Flutter

Егор Долгов · 05.07.2019
This article was written for an older Flutter version and is being updated. Some code may not compile on the current version.

Для обмена данными между клиентом (мы рассматриваем приложение на смартфоне) и сервером (веб-сервером) в основном используется http протокол или его расширение https для безопасной передачи данных.

В Dart есть одноименный пакет http , подключается он в файле зависимостей и метаданных pubspec.yaml :

dependencies:
 flutter:
   sdk: flutter
 http: ^0.12.0

Для подключения в самом проекте нужно указать:

import 'package:http/http.dart' as http;

Ключевое слово as — указывает на то что подключаемые методы из пакета будут доступны через объект-имя http , к примеру:

  • http.get(...)
  • http.post(...)
  • http.put(...)
  • и т.д.

Список методов можно посмотреть в исходном коде пакета: github.com/dart-lang/http/blob/master/lib/http.dart

Эти методы тесно связаны с REST API , но пакет http не ограничивает нас этим. С его помощью мы можем написать любой свой API, использующий http протокол, например JSON-pure API .

GET запросы к серверу

Сетевые запросы к серверу относительно медленные, поэтому их выполнение происходит в отдельных потоках с помощью асинхронных методов. Это значит, что для того чтобы обработать результат запроса с сервера, нужно вначале его дождаться.

Список методов нашего тестового АПИ и примеры можно посмотреть здесь: json.flutter.su

Сделаем запрос к нашему тестовому серверу: https://json.flutter.su/echo

В ответ мы получим:

type:echo
method:GET
ip:88.201.***.***
date:Tuesday, 08-Jan-2019 20:43:32 Europe/Moscow

Код для выполнения асинхронного GET запроса к серверу и вывода в консоль:

http.get('https://json.flutter.su/echo').then((response) {
  print("Response status: ${response.statusCode}");
  print("Response body: ${response.body}");
}).catchError((error){
  print("Error: $error");
});

После выполнения запроса происходит обработка результата response , вложенной функции в .then((responce){...обработка результата...}) .

Если возникает ошибка, например, при отсутствии интернета, срабатывает вложенный метод .catchError((error){...обработка ошибки...}) .

HTTPS GET запрос к серверу
HTTPS GET запрос к серверу

В нашем примере response.statusCode == 200 , это стандартный код успешного запроса. Для других методов REST API он может быть иным.

Содержимое ответа находится в response.body .

Тот же самый запрос можно описать без вложенной функции, и вызвать синхронно с помощью await :

var response = await http.get('https://json.flutter.su/echo');
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");

В get запросах мы можем передавать get-параметры в адресе строки: https://json.flutter.su/echo? id=1

POST запросы к серверу

В post запросах можно передавать данные в теле запроса с помощью параметра body и кодировку encoding если она отличается от utf-8 (по умолчанию), синхронное выполнение метода с помощью await :

var response = await http.post('https://json.flutter.su/echo', body: {'name':'test','num':'10'});
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");

В параметре body вы можете передать: [String], [List<int>], [Map<String, String>].

Headers — передача заголовков

Еще один параметр который может быть указан для всех методов — это заголовки headers (Map<String, String>) . В заголовках чаще всего передаются данные для авторизации и для выбора возвращаемых/передаваемых данных.

var response = await http.post('https://json.flutter.su/echo',
  headers: {'Accept':'application/json','Authorization':'Basic YWxhZGRpbjpvcGVuc2VzYW1l'}
);

Try и catch — обработка ошибок

При использовании любых сетевых запросов необходимо использовать обработку ошибок и исключительных ситуаций try {...} catch(error){...}

try {
  var response = await http.get('https://json.flutter.su/echo');
  print("Response status: ${response.statusCode}");
  print("Response body: ${response.body}");
} catch (error) {
  print(error);
}

Данная конструкция позволит обработать ситуации когда нет доступа к сетевому ресурсу: выключена передача данных, отсутствует связь с сервером или указан неверный сетевой адрес. В блоке try{...} выполняется код программы, если он не может быть выполнен — выполняется блок catch(error){...} .

Пример программы

Здесь мы приведем только код функций кнопок с сетевыми запросами, а весь код программы для удобства мы разместили в репозитории сервиса GitHub

_sendRequestGet() {
 if(_formKey.currentState.validate()) {
   _formKey.currentState.save();//запуск функции сохранения данных из формы в переменную _url

   http.get(_url).then((response){
     _status = response.statusCode;
     _body = response.body;

     setState(() {});//перестраиваем виджет окна для отображения изменений _status и _body
   }).catchError((error){
     _status = 0;
     _body = error.toString();

     setState(() {});//перестраиваем виджет окна в случае сетевой ошибки
   });
 }
}//_sendRequestGet

_sendRequestPost() async {
 if(_formKey.currentState.validate()) {
   _formKey.currentState.save();//запуск функции сохранения

   try {
     var response = await http.post(_url);

     _status = response.statusCode;
     _body = response.body;
   } catch (error) {
     _status = 0;
     _body = error.toString();
   }
   setState(() {});//перестраиваем виджет окна
 }
}//_sendRequestPost

_sendRequestPostBodyHeaders() async {
 if(_formKey.currentState.validate()) {
   _formKey.currentState.save();//запуск функции
   try {
     var response = await http.post(_url,
                   body: {'name':'test','num':'10'},
                   headers: {'Accept':'application/json'}
                   );

     _status = response.statusCode;
     _body = response.body;
   } catch (error) {
     _status = 0;
     _body = error.toString();
   }
   setState(() {});//перестраиваем виджет окна
 }
}//_sendRequestPost

Скопируйте репозиторий с помощью команды git clone https://github.com/flutter-tutorial/test_http.git или скачайте как zip архив.

Так как в репозитории нет всех файлов для построения android и ios приложения, выполните команду, после загрузки, как при создании нового проекта: flutter create test_http test_http — имя директории скопированного проекта.

Если вы скопировали проект в Android Studio , то после команды «flutter create ...», необходимо нажать на кнопку Restart Dart Analysis Server, иначе ошибки не убрать.

Restart Dart Analysis Server
Restart Dart Analysis Server

Подробнее про копирование существующих Flutter проектов с помощью git, мы опишем в отдельном уроке.

Пример программы
Пример программы
Пример программы
Пример программы

В следующем уроке по HTTP запросам мы рассмотрим создание своего пакета для сетевого общения с сервером, и посмотрим как заменить http.post, http.get и т.д.