Что такое StreamBuilder в Flutter?

Ответ

StreamBuilder — это виджет Flutter, который автоматически перестраивает свой дочерний виджет в ответ на новые данные из Stream. Он управляет подпиской на поток и предоставляет снимок (AsyncSnapshot) текущего состояния потока (ожидание, данные, ошибка, завершение).

Основные параметры:

  • stream: Stream, на который подписывается виджет.
  • builder: Функция, возвращающая виджет на основе AsyncSnapshot<T>.

Пример использования:

StreamBuilder<int>(
  stream: myCounterStream, // Stream<int>
  builder: (context, snapshot) {
    // Проверяем состояние потока
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator();
    }
    if (snapshot.hasError) {
      return Text('Ошибка: ${snapshot.error}');
    }
    // Данные доступны
    return Text('Значение: ${snapshot.data}');
  },
)

Практические нюансы:

  • StreamBuilder сам управляет жизненным циклом подписки — отписывается при демонтаже виджета.
  • Для потоков, которые должны существовать дольше жизни виджета (например, глобальное состояние), управление подпиской через StreamBuilder безопасно и удобно.
  • AsyncSnapshot.connectionState позволяет точно отображать состояние загрузки (waiting, active, done).

Ответ 18+ 🔞

А, StreamBuilder, говоришь? Ну это же, блядь, классика жанра, как бутерброд с колбасой — без него никуда. Представь себе такую картину: у тебя есть поток данных, который плюётся значениями, как старый принтер бумагой — то тихо, то вдруг «трррр!». А ты сидишь и думаешь: «Какого хуя мне теперь с этим делать? Как эти цифры на экран вывалить?». Вот тут-то наш герой и появляется.

StreamBuilder — это такой хитрожопый виджет, который сам, сука, подписывается на твой Stream и начинает за ним следить, как ревнивый муж. Получил новую порцию данных — сразу же перерисовывает всё, что внутри него, с новыми данными. И всё это без твоей прямолинейной возни с StreamSubscription, которую ты наверняка забудешь отписать, и потом приложение будет течь, как решето. Он сам управляет этой подпиской — создался виджет, подписался, уничтожился — отписался. Красота, ёпта!

Смотри, как он устроен. Кидаешь ему два главных параметра:

  • stream — собственно, сам поток, на который нужно подслушивать. Можешь передать хоть null, но тогда он будет как пень — ничего не делать.
  • builder — это мозги операции. Функция, которой он отдаёт AsyncSnapshot<T>. А этот снапшот — он как сводка с фронта: то ли данные ещё едут, то ли уже приехали, то ли вообще поезд с рельс съехал.

Вот смотри, как это в коде выглядит, тут всё просто, как три копейки:

StreamBuilder<int>(
  stream: myCounterStream, // Допустим, Stream<int>, который плюётся числами
  builder: (context, snapshot) {
    // А теперь начинается магия. Смотрим, что там снапшот нам принёс.
    if (snapshot.connectionState == ConnectionState.waiting) {
      // Данные ещё грузятся, поток только запустился.
      // Показываем крутилку, чтобы пользователь не думал, что всё накрылось медным тазом.
      return CircularProgressIndicator();
    }
    if (snapshot.hasError) {
      // Ой, ёб твою мать! Что-то пошло не так. Поток выплюнул ошибку.
      // Выводим её, пусть пользователь тоже пострадает.
      return Text('Ошибка: ${snapshot.error}');
    }
    // Всё, пиплы, данные на месте! Можно спокойно выводить.
    return Text('Значение: ${snapshot.data}');
  },
)

А теперь, внимание, практические фишки, без которых ты можешь обосраться:

  • За жизненным циклом он следит сам. Это главный плюс. Создал StreamBuilder — он подписался. Удалил виджет со страницы — он отписался. Никаких утечек памяти, всё чисто. Просто иногда от такой заботливости сам от себя охуеваешь.
  • Идеально для глобальных потоков. Есть у тебя какой-нибудь StreamController, который висит в состоянии приложения и вещает на всю арену? StreamBuilder — твой лучший друг. Он безопасно подключится, послушает и отключится, когда надо.
  • Не игнорируй connectionState. Это мощный инструмент, а не просто галочка. waiting — только подключились, данных ещё нет. active — данные пошли рекой, всё ок. done — поток завершился, всё, приехали. Используй эти состояния, чтобы интерфейс был умным, а не тупо показывал «ничего» или крутилку вечность. Пользователь — не дурак, он чувствует, когда его за лоха держат.

Короче, StreamBuilder — это твой легавый, который берёт всю грязную работу с асинхронностью на себя. Ты просто говоришь: «Вот поток, вот как рисовать, когда что приходит», — а он уже сам всё делает. Главное — не переусердствуй и не вкладывай их друг в друга бездумно, а то получится ёперный театр, где всё мигает и перерисовывается без причины. Доверяй, но проверяй, что и в каком состоянии рендеришь.