Блок, флаттер и навигация - PullRequest
0 голосов
/ 09 января 2019

Так что, как и большинство, я новичок в Блоке, трепещу, шатаюсь и оборачиваюсь. Я погуглил, просмотрел сообщения здесь, но не нашел никаких ответов.

Так что речь идет о навигации по блоку и флаттеру. Возьмите пример входа в систему. Таким образом, есть страница входа в систему с блоком позади нее, и в какой-то момент кто-то нажимает кнопку для входа.

Таким образом, мы можем вызвать функцию в блоке, которая выполняет проверку. Я думаю, что это против строгого подхода, но я вижу, что люди делают это. Но тогда, если вход успешен, как вы переходите к следующему экрану? Вы не должны ориентироваться в блоке?

Но если эта страница входа в систему использует StreamBuilder для изменения состояния, вы не можете добавить навигацию в компоновщик, не так ли? Вы не можете вернуть навигацию, вы возвращаете виджеты.

Initstate - это то место, где вы могли бы перемещаться, но можете ли вы иметь построитель потоков в initstate, который прослушивает изменения состояния в блоке?

Сейчас все это немного сбивает с толку, но я настойчив, так как это предполагается, что - путь вперед ...

спасибо Пол

1 Ответ

0 голосов
/ 10 мая 2019

Чтобы раскрыть миф о том, что BLoC - это путь прямо с пути: не существует идеального способа обработки состояния. Каждая архитектура управления государством решает некоторые проблемы лучше, чем другие; всегда есть компромиссы, и важно учитывать их при выборе архитектуры.

Как правило, хорошая архитектура практична : она масштабируема и расширяема, но требует минимальных накладных расходов. Поскольку взгляды людей на осуществимость различаются, архитектура всегда включает в себя мнение, поэтому примите следующее с большой долей соли, так как я изложу свое личное мнение о том, как использовать BLoC для вашего приложения.

BLoC - очень многообещающий подход к управлению состоянием во Флаттере из-за одного компонента подписи: потоков. Они позволяют отделить пользовательский интерфейс от бизнес-логики и хорошо сочетаются с подходом Flutter-ish, заключающимся в восстановлении целых поддеревьев виджетов после их устаревания. Естественно, что каждое сообщение от и до BLoC должно использовать потоки, верно?

+----+  Stream   +------+
| UI | --------> | BLoC |
|    | <-------- |      |
+----+   Stream  +------+

Ну, вроде как.

Важно помнить, что архитектура управления состоянием - это средство для достижения цели ; Вы должны не просто делать что-то ради этого, но быть непредвзятым и тщательно оценивать плюсы и минусы каждого варианта. Причина, по которой мы отделяем BLoC от пользовательского интерфейса, заключается в том, что BLoC не нужно заботиться о том, как структурирован пользовательский интерфейс, он просто предоставляет несколько простых простых потоков, и все, что происходит с данными, является обязанностью пользовательского интерфейса.

Но хотя потоки оказались фантастическим способом передачи информации из BLoC в пользовательский интерфейс, они добавляют ненужные накладные расходы в другом направлении: Потоки были предназначены для транспортировки непрерывных потоков данных (даже в названии), но в большинстве случаев пользовательский интерфейс просто должен инициировать отдельные события в BLoC. Вот почему иногда вы видите Stream<void> s или аналогичные хакерские решения¹, просто чтобы придерживаться строго BLoC-y способа делать вещи.

Кроме того, если бы мы выдвигали новые маршруты на основе потока из BLoC, BLoC в основном контролировал бы поток пользовательского интерфейса, но наличие кода, который непосредственно контролирует как пользовательский интерфейс, так и бизнес-логику, - это именно то, что мы пытались предотвратить!

Вот почему некоторые разработчики (включая меня) просто ломают голову над полностью потоковым решением и используют пользовательский способ запуска событий в BLoC из пользовательского интерфейса. Лично я просто использую вызовы методов (которые обычно возвращают Future s), чтобы вызвать события BLoC:

+----+   method calls    +------+
| UI | ----------------> | BLoC |
|    | <---------------- |      |
+----+   Stream, Future  +------+

Здесь BLoC возвращает Stream с для данных, которые являются «живыми», и Future с как ответы на вызовы методов.

Давайте посмотрим, как это может сработать для вашего примера:

  • BLoC может предоставить Stream<bool> того, вошел ли пользователь в систему или даже Stream<Account>, где Account содержит информацию об учетной записи пользователя.
  • BLoC может также предоставить асинхронный метод Future<void> signIn(String username, String password), который ничего не возвращает, если вход выполнен успешно или в противном случае выдает ошибку.
  • Пользовательский интерфейс может самостоятельно обрабатывать управление вводом и запускать что-то вроде следующего при нажатии кнопки входа в систему:
try {
  setState(() => _isLoading = true); // This could display a loading spinner of sorts.
  await Bloc.of(context).signIn(_usernameController.text, _passwordController.text);
  Navigator.of(context).pushReplacement(...); // Push logged in screen.
} catch (e) {
  setState(() => _isLoading = false);
  // TODO: Display the error on the screen.
}

Таким образом, вы получаете хорошее разделение интересов:

  • BLoC действительно просто делает то, что должен делать - обрабатывать бизнес-логику (в данном случае вход пользователя).
  • Пользовательский интерфейс просто заботится о двух вещах:
    • Отображение пользовательских данных от Stream s и
    • реагирование на действия пользователя путем их запуска в BLoC и выполнения действий пользовательского интерфейса в зависимости от результата .²

Наконец, я хочу отметить, что это единственное возможное решение, которое эволюционировало с течением времени, испробовав различные способы обработки состояний в сложном приложении. Важно узнать различные точки зрения о том, как может работать управление состоянием, поэтому я призываю вас углубиться в эту тему, возможно, наблюдая за сеансом"Прагматическое управление состояниями во флаттере" * от Google I / O .

EDIT : только что нашел эту архитектуру в образцах архитектуры Брайана Эгана , где она называется "Simple BLoC". Если вы хотите познакомиться с различными архитектурами, я действительно рекомендую взглянуть на репозиторий.


¹ Это становится еще страшнее при попытке предоставить несколько аргументов для действия BLoC - потому что тогда вам нужно будет определить класс-обертку, чтобы просто передать его в поток.

² Я делаю признаю, что он становится немного уродливым при запуске приложения: вам понадобится своего рода заставка, которая просто проверяет поток BLoC и перенаправляет пользователя на соответствующий экран в зависимости от того, он / она вошел или нет. Это исключение из правила происходит из-за того, что пользователь выполнил действие - запускает приложение, - но среда Flutter напрямую не позволяет нам подключиться к этому (по крайней мере, не так элегантно, насколько я знаю).

...