Я новичок в шаблоне BLoC, и у меня возник вопрос, который я не смог найти в другом месте. Используя библиотеку flutter_bloc, у меня есть доступ к виджету BlocBuilder, который будет перестраиваться при изменении состояния BLoC. Поскольку я обрабатываю состояние независимо от фреймворка, необходимо ли объявлять родительский виджет (скажем, карту, содержащую данные из BLoC) как Stateful?
Мне удалось успешно реализовать BlocBuilders в качестве дочерних элементов виджетов с сохранением состояния и без сохранения состояния, но я не смог решить, какой из них будет наилучшей практикой, или будет ли вообще какой-либо случай, когда наличие состояния будет необходимо.
Думаю, я был бы на правильном пути, если бы сказал, что Stateless — это хорошо, если вам не нужно ничего обновлять за пределами BlocBuilder, но вам понадобится Stateful, если вы добавите что-то вроде RefreshIndicator и должны будете реализовать логику для этого. (и условно передавать события в BLoC). Это правильно?
Я уверен, что я слишком много объясняю здесь, но в духе этого я предоставил код ниже, если он поможет понять мой вопрос.
Вот упрощенная реализация Stateless, относящаяся к моему проекту:
class WeatherCard extends StatelessWidget {
/// You can assume that the following is happening:
/// 1) There is a BlocProvider in the parent widget which
/// will implement this WeatherCard.
///
/// 2) The WeatherLoaded state in the WeatherBloc provides an
/// instance of a WeatherModel which contains all of the data
/// from a weather API.
///
@override
Widget build(BuildContext context) {
return Card(
child: BlocBuilder(
bloc: BlocProvider.of<WeatherBloc>(context),
builder: (BuildContext context, WeatherState state) {
if (state is WeatherLoading) {
return Text('Loading...');
} else if (state is WeatherLoaded) {
return Text(state.weatherModel.temp.toString());
} else {
return Text('Error!');
}
}
);
}
}
И реализация с сохранением состояния:
// You can make the same assumptions here as in the Stateless implementation.
class WeatherCard extends StatefulWidget {
@override
_WeatherCardState createState() => _WeatherCardState();
}
class _WeatherCardState extends State<WeatherCard> {
@override
Widget build(BuildContext context) {
return Card(
child: BlocBuilder(
bloc: BlocProvider.of<WeatherBloc>(context),
builder: (BuildContext context, WeatherState state) {
if (state is WeatherLoading) {
return Text('Loading...');
} else if (state is WeatherLoaded) {
return Text(state.weatherModel.temp.toString());
} else {
return Text('Error!');
}
}
);
}
}
Используя Bloc, вы сможете почти полностью избежать объявления виджетов с отслеживанием состояния, хотя, безусловно, возможно, а иногда и имеет смысл использовать виджеты с отслеживанием состояния или другие стратегии управления состоянием.
Если вы условно передаете логику в блок, вы можете подумать о переносе условной логики в сам блок и просто передать события, которые запускают условные операторы.
Также определенно возможно иметь несколько потоков, объявленных в блоке, и несколько StreamBuilders в пользовательском интерфейсе, прослушивающих один и тот же блок, хотя я не знаю, возможно ли это с библиотекой flutter_bloc. Похоже, вы ограничены одним потоком на блок, если используете flutter_bloc. Вместо этого вы также можете использовать стратегию/BlocProvider, описанную здесь.
Для некоторых небольших изменений в пользовательском интерфейсе, которые не оказывают никакого/сильного влияния на логику программы, может быть проще использовать виджет с состоянием для обработки состояния, чем сохранять состояние в блоке. На самом деле нет правильного или неправильного ответа для всех ситуаций, вам решать, что будет легче создавать и поддерживать в долгосрочной перспективе. Но ваша программа, вероятно, будет легче читать и легче найти то, что вы хотите изменить, если вы сохраните свою архитектуру последовательной. Итак, если вы используете блок, это будет означать обработку всего состояния в блоках и построение вашего пользовательского интерфейса полностью или почти полностью из виджетов без состояния.