Корпус строительных лесов перестраивается при открытии меню ящика.
У меня есть виджет с отслеживанием состояния, который строит эшафот. Я использую ящик в эшафоте для бокового меню. Кроме того, тело Scaffold - это FutureBuilder, который получает данные из базы данных firestore и отображает информацию в Card в теле. Кажется, возникла проблема при открытии ящика, из-за которой тело перестраивается, и FutureBuilder снова запрашивает данные. Это снова происходит снова, когда выдвигается ящик. У меня есть другие кнопки в Scaffold на панели приложений и в bottomNavigationBar для перехода к разным маршрутам. При перемещении по этим маршрутам тело не восстанавливается. Может ли кто-нибудь помочь, почему это происходит с ящиком?
Ниже приведен фрагмент кода.
благодаря
class CustomScaffoldState extends State<CustomScaffold> {
Widget build(BuildContext context) {
return Scaffold(
drawer: sideMenu(widget.username),
body: FutureBuilder(
future: getData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
//return the Card with Info
}
if (snapshot.hasError) {
print('Error');
}
else{
//return a CircularProgressIndicator
}
}
));
//appbar and bottomNavigation bar also implemented
}
}
1 ответ
Когда выдвижной ящик или программная клавиатура открываются, состояние экрана меняется, а иногда и метод сборки перезагружается автоматически, пожалуйста, проверьте эту ссылку для получения дополнительной информации.
Метод сборки разработан таким образом, что он должен быть чистым / без побочных эффектов. Это связано с тем, что многие внешние факторы могут запускать сборку нового виджета, например:
Маршрут pop / push Изменение размера экрана, обычно из-за внешнего вида клавиатуры или изменения ориентации Родительский виджет воссоздал свой дочерний виджет InheritedWidget, от которого зависит виджет (шаблон Class.of(context)). Это означает, что метод сборки не должен запускать HTTP-вызов или изменять любое состояние.
Как это связано с вопросом?
Проблема, с которой вы столкнулись, заключается в том, что ваш метод сборки имеет побочные эффекты / не является чистым, что затрудняет посторонний вызов сборки.
Вместо того, чтобы предотвращать вызов сборки, вы должны сделать свой метод сборки чистым, чтобы его можно было вызывать в любое время без каких-либо последствий.
В случае вашего примера вы должны преобразовать свой виджет в StatefulWidget, а затем извлечь этот HTTP-вызов в initState вашего состояния:
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
Future<int> future;
@override
void initState() {
future = Future.value(42);
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: future,
builder: (context, snapshot) {
// create some layout here
},
);
}
}
Я это уже знаю. Я пришел сюда, потому что очень хочу оптимизировать перестроения
Также возможно сделать виджет способным к перестройке, не заставляя его дочерние элементы тоже строить.
Когда экземпляр виджета остается прежним; Flutter намеренно не восстанавливает детей. Это означает, что вы можете кэшировать части своего дерева виджетов, чтобы предотвратить ненужные перестроения.
Самый простой способ - использовать конструкторы dart const:
@override
Widget build(BuildContext context) {
return const DecoratedBox(
decoration: BoxDecoration(),
child: Text("Hello World"),
);
}
Благодаря этому ключевому слову const экземпляр DecoratedBox останется прежним, даже если сборка вызывалась сотни раз.
Но вы можете добиться того же результата вручную:
@override
Widget build(BuildContext context) {
final subtree = MyWidget(
child: Text("Hello World")
);
return StreamBuilder<String>(
stream: stream,
initialData: "Foo",
builder: (context, snapshot) {
return Column(
children: <Widget>[
Text(snapshot.data),
subtree,
],
);
},
);
}
В этом примере, когда StreamBuilder получает уведомление о новых значениях, поддерево не будет перестраиваться, даже если StreamBuilder/Column это сделает. Это происходит потому, что из-за закрытия экземпляр MyWidget не изменился.
Этот паттерн часто используется в анимации. Типичное использование - AnimatedBuilder и все переходы, такие как AlignTransition.
Вы также можете сохранить поддерево в поле своего класса, хотя это не рекомендуется, так как оно нарушает функцию горячей перезагрузки.