На каком потоке выполняются сетевые запросы в Dart/Flutter?

Ответ

В Dart сетевые запросы выполняются асинхронно, не блокируя основной изолят (Isolate), в котором работает UI. Dart использует event-loop и модель Future/async/await.

Ключевые моменты:

  • Код await освобождает event-loop, позволяя выполняться другим задачам (обработке ввода, таймерам, микрозадачам).
  • Сам ввод-вывод (IO) делегируется операционной системе, и когда ответ готов, Future завершается, и выполнение кода после await продолжается в том же изоляте.
  • Для тяжелых синхронных вычислений в ответе на сетевой запрос нужно использовать compute или Isolate.spawn, чтобы не заблокировать event-loop.

Пример с http:

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

Future<void> fetchUserData() async {
  try {
    // Запрос выполняется асинхронно. Пока система ждет ответа,
    // event-loop может обрабатывать другие события.
    final response = await http.get(
      Uri.parse('https://api.example.com/user'),
    );
    if (response.statusCode == 200) {
      // Обработка ответа происходит уже в основном изоляте.
      final data = jsonDecode(response.body);
      print('User: ${data['name']}');
    }
  } catch (e) {
    print('Request failed: $e');
  }
}

Почему это важно: Если бы запросы выполнялись синхронно в UI-потоке, интерфейс бы "замирал" на время ожидания ответа от сервера.

Ответ 18+ 🔞

Ага, слушай, тут про Dart и сетевые запросы надо бы разжевать, а то народ путается, как это всё работает под капотом. Ёпта, представь себе бармена в адски загруженном баре — это твой event-loop. Если он будет стоять и ждать, пока на кухне приготовят десять порций картошки фри для одного заказа, весь остальной народ перед стойкой просто передохнет от жажды и злости. Так вот, await — это как бармен, который принял сложный заказ, отправил его на кухню (в операционную систему), и пошёл наливать пиво другим клиентам, пока там готовят. Гениально же!

Короче, главные фишки:

  • Когда пишешь await, ты не блокируешь весь свой основной поток (изолят), где интерфейс рисуется. Ты просто говоришь: "Ладно, я тут подожду, а ты, event-loop, иди другие дела делай — кнопки нажимай, анимации крути".
  • Вся реальная грязная работа с сетью (ожидание ответа от сервера) происходит где-то там, глубоко в недрах ОС. Дарт ей делегирует эту почетную миссию. Как только ответ приплыл, система пинает твой Future и говорит: "Эй, дружок, твои данные готовы, продолжай работать". И выполнение кода после await спокойно возобновляется.
  • Вот тут внимание, очень важно: Если в ответе от сервера тебе прилетела не просто JSON-ка, а, например, гигабайтный файл, который нужно как-то хитро распарсить или посчитать в нём все запятые — это уже тяжелая синхронная работа. Если её делать прямо в UI-потоке, то твой бармен (event-loop) снова упрётся лбом в стену и будет только этим и занят. Интерфейс опять зависнет, пользователь охуеет. Для такого безобразия есть специальные инструменты — compute или Isolate.spawn. Это как нанять отдельного работника на кухню специально для чистки этой ебушки-воробушки картошки, чтобы бармен мог продолжать разливать.

Смотри, как это выглядит на практике с пакетом http:

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

Future<void> fetchUserData() async {
  try {
    // Вот тут делается запрос. Пока система ждёт ответа от сервера,
    // твой event-loop не тупит, а живёт полной жизнью.
    final response = await http.get(
      Uri.parse('https://api.example.com/user'),
    );
    if (response.statusCode == 200) {
      // А вот это уже происходит в основном потоке, когда данные пришли.
      // JSON-парсинг обычно быстрый, но если он огромный — см. пункт выше про изоляты.
      final data = jsonDecode(response.body);
      print('User: ${data['name']}');
    }
  } catch (e) {
    print('Request failed: $e');
  }
}

Итог для самых понятливых: Если бы запросы были синхронными, твой UI вставал бы колом на всё время ожидания. Это пиздец как плохо. Асинхронность через async/await делает так, что приложение остаётся отзывчивым, пока где-то там летают байты по сети. Волнение ебать, но система-то умная, работает. Главное — не нагружай основной поток ебаниной, которая требует овердохуища вычислений. Для этого есть другие механизмы.