Во-первых, я должен сказать, что я не уверен, является ли stackoverflow подходящим местом, чтобы спросить об этом, но у меня не с кем спросить, кроме сообщества, потому что мы работаем в небольшом стартапе, где нет разработчиков флаттера, кроме двух из нас.
Я (около года в разработке и около половины года изучаю флаттер) и один своего рода «старший разработчик мобильных приложений с 10-летним опытом» ведут ожесточенные дискуссии.
В топике c обсуждения используется не окончательное поле в виджете без сохранения состояния. Он делает это, он пишет такой код. И он говорит, что это лучший способ решить его проблемы. Я говорю, что это плохая идея, либо ему нужен виджет с сохранением состояния, либо его дизайн плохой, и ему не нужно поле без финала.
Итак, мой вопрос: есть ли ситуация, в которой использование неконечного поля в виджете без состояния оправдано?
Его аргументы:
- Мы используя шаблон BLo C, и поскольку в StatelessWidget у нас есть BlocBuilder, этот StatelessWidget имеет состояние.
- Глупый Дарт Линтер не знает нашу «ситуацию BLo C»
- Если мы будем использовать виджет с сохранением состояния, читаемость кода ухудшится.
- Если мы будем Использование виджета с отслеживанием состояния приводит к дополнительным накладным расходам.
Я знаю, что первые два аргумента глупы, и стоит обсуждать только четвертый аргумент.
Возможный дубликат этого вопроса также не убеждает моего коллегу. Флаттер: изменяемые поля в виджетах без состояния
Пожалуйста, взгляните на его код:
class GameDiscussThePicture extends StatelessWidget {
GameDiscussThePicture();
CarouselSlider _slider;
@override
Widget build(BuildContext context) {
return BlocBuilder(
bloc: BlocProvider.of<ChatBloc>(context),
condition: (previousState, state) {
return previousState != GameClosed();
},
builder: (context, state) {
if (state is GameDiscussTopicChanged) {
_showPictureWith(context, state.themeIndex);
} else if (state is GameClosed) {
Navigator.of(context).pop();
return Container();
}
final _chatBloc = BlocProvider.of<ChatBloc>(context);
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 255, 255, 255),
leading: BackButton(
color: Color.fromARGB(255, 12, 12, 13),
onPressed: () => BlocProvider.of<ChatBloc>(context).add(GameCancel()),
),
),
//SafeArea
body: DecoratedBox(
decoration: BoxDecoration(color: Color.fromARGB(255, 240, 240, 240)),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 15),
_carouselSlider(context),
Container(
height: 88,
child: DecoratedBox(
decoration: BoxDecoration(color: Color.fromARGB(255, 255, 255, 255)),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (_chatBloc.partnerAvatar() != null) Image.network(_chatBloc.partnerAvatar(), fit: BoxFit.cover, width: 75.0),
if (_chatBloc.partnerAvatar() == null) Text('RU', style: TextStyle(fontSize: 22)),
Padding(
padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(_chatBloc.partnerName(), style: TextStyle(fontSize: 20, fontWeight: FontWeight.normal),),
ChatStopwatch(),
// Text('До конца 06:33', style: TextStyle(fontSize: 14, fontWeight: FontWeight.normal),),
],
)
),
// FlatButton(
// child: Image.asset('assets/images/mic_off.png', width: 30, height: 30,),
// onPressed: () => print('mic off pressed'),
// ),
FlatButton(
child: Image.asset('assets/images/hang_off.png', width: 60, height: 60,),
onPressed: () => ChatHelper.confirmEndingDialog(context)
),
]),
))
],
),
),
],
),
),
);
});
}
@widget
Widget _carouselSlider(BuildContext context) {
final chatBloc = BlocProvider.of<ChatBloc>(context);
_slider = CarouselSlider(
height: 600.0,
viewportFraction: 0.9,
reverse: false,
enableInfiniteScroll: false,
initialPage: chatBloc.gameDiscussCurrentIdx,
onPageChanged: (index) {
final chatBloc = BlocProvider.of<ChatBloc>(context);
if (chatBloc.gameDiscussCurrentIdx < index) {
chatBloc.add(GameDiscussTopicChange(themeIndex: index));
} else {
_slider.animateToPage(chatBloc.gameDiscussCurrentIdx, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);
}
},
items: chatBloc.gameDiscussPictures.map((item) {
return Builder(
builder: (BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(horizontal: 5.0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item.titleEn, style: Styles.h3),
SizedBox(height: 15.0,),
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(15.0)),
child: Image.network(item.getImageUrl(), fit: BoxFit.cover, width: MediaQuery.of(context).size.width),
)
]
),
);
},
);
}).toList(),
);
return _slider;
}
_onPictureChanged(BuildContext context, int index) {
final chatBloc = BlocProvider.of<ChatBloc>(context);
if (chatBloc.gameDiscussCurrentIdx < index) {
chatBloc.add(GameDiscussTopicChange(themeIndex: index));
} else {
_slider.animateToPage(chatBloc.gameDiscussCurrentIdx, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);
}
}
_showPictureWith(BuildContext context, int index) {
final chatBloc = BlocProvider.of<ChatBloc>(context);
chatBloc.gameDiscussCurrentIdx = index;
_slider.animateToPage(chatBloc.gameDiscussCurrentIdx, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);
}
}