Как соотносятся виджеты с сохранением состояния и без учета состояния во Flutter?
Виджет с состоянием определяется как любой виджет, который меняет свое состояние в течение своего времени жизни. Но это очень распространенная практика для StatelessWidget
иметь StatefulWidget
как один из его детей. не StatelessWidget
стать государством, если оно имеет StatefulWidget
как один из его детей?
Я пытался заглянуть в документацию как часть кода StatelessWidget
, но не мог понять, как StatelessWidget
могу иметь Statefulwidget
как его дети и до сих пор остаются StatelessWidget
,
Каково соотношение и различие между виджетами с состоянием и без состояний во Flutter?
6 ответов
StatelessWidget
никогда не восстановит (если не связано с InheritedWidget
). StatefulWidget
может Это золотое правило.
НО любой виджет можно перекрасить в любое время.
Только отсутствие состояния означает, что все его свойства являются неизменяемыми, и что единственный способ изменить их - создать новый экземпляр этого виджета. Например, он не блокирует дерево виджетов.
Но тебя не должно волновать тип твоих детей. Это не имеет никакого влияния на вас.
StatefulWidget против StatelessWidget.
StatelessWidget: - Виджет, который не требует изменяемого состояния.
Виджет без состояния - это виджет, который описывает часть пользовательского интерфейса путем создания совокупности других виджетов, которые более конкретно описывают пользовательский интерфейс. Процесс построения продолжается рекурсивно до тех пор, пока описание пользовательского интерфейса не станет полностью конкретным (например, полностью состоит из RenderObjectWidgets, которые описывают конкретные RenderObjects).
stateless
Виджет полезен, когда описываемая вами часть пользовательского интерфейса не зависит ни от чего, кроме информации о конфигурации в самом объекте и BuildContext, в котором виджет раздувается. Для композиций, которые могут динамически изменяться, например, из-за наличия внутреннего синхронизируемого состояния или в зависимости от некоторого состояния системы, рассмотрите возможность использованияStatefulWidget
,
class GreenFrog extends StatelessWidget {
const GreenFrog({ Key key }) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(color: const Color(0xFF2DBD3A));
}
}
StatefulWidget: - Виджет, который имеет изменяемое состояние.
- Виджеты с отслеживанием состояния полезны, когда часть описываемого вами пользовательского интерфейса может динамически меняться.
Когда Флаттер строит StatefulWidget
создает объект State. В этом объекте хранятся все изменяемые состояния этого виджета.
Понятие государства определяется двумя вещами:
1) Данные, используемые виджетом, могут измениться.
2) Данные не могут быть прочитаны синхронно, когда виджет построен. (Все состояние должно быть установлено к моменту вызова метода сборки).
StatefulWidget жизненный цикл
Жизненный цикл имеет следующие упрощенные этапы:
1- createState (): - когда Flutter получает команду на создание StatefulWidget, он немедленно вызывает createState()
,
Создает изменяемое состояние для этого виджета в заданном месте дерева.
Подклассы должны переопределить этот метод для возврата вновь созданного экземпляра их связанного подкласса State:
@override
_MyState createState() => _MyState();
2-mount == true: - Все виджеты имеют свойство bool this.mounting. Оказывается, когда buildContext
назначен. Ошибка вызывать setState, когда виджет отключен. Находится ли этот объект State в дереве.
После создания объекта State и перед вызовом
initState
каркас "монтирует" объект State, связывая его сBuildContext
, Государственный объект остается смонтированным до каркаса
звонкиdispose()
после чего рамки никогда не спросят
Государственный объект, чтобы построить снова.Вызывать setState является ошибкой, если не установлено true.
bool get mounted => _element != null;
3- initState (): - это первый метод, вызываемый при создании виджета (конечно, после конструктора класса).
initState
вызывается один раз и только один раз. Должно называться super.initState().
Инициализируйте данные, которые зависят от определенного BuildContext для созданного экземпляра виджета.
Инициализируйте свойства, которые полагаются на эти родительские виджеты в дереве.
Подписаться на потоки,
ChangeNotifiers
или любой другой объект, который может изменить данные в этом виджете.
@override
initState() {
super.initState();
// Add listeners to this class
cartItemStream.listen((data) {
_updateWidget(data);
});
}
4- didChangeDependencies (): - Вызывается при изменении зависимости этого объекта состояния.
Этот метод также вызывается сразу после initState. Безопасно вызывать BuildContext.inheritFromWidgetOfExactType из этого метода.
Подклассы редко переопределяют этот метод, потому что каркас всегда вызывает build после изменения зависимостей. Некоторые подклассы переопределяют этот метод, потому что им нужно выполнять дорогостоящую работу (например, выборки по сети), когда их зависимости меняются, и эта работа будет слишком дорогой для каждой сборки.
@protected
@mustCallSuper
void didChangeDependencies() { }
5- build (): - описывает часть пользовательского интерфейса, представленную виджетом.
Фреймворк вызывает этот метод в ряде различных ситуаций:
- После вызова initState.
- После вызова didUpdateWidget.
- После получения звонка в setState.
- После того, как зависимость этого состояния объекта изменится (например, InheritedWidget, на который ссылаются предыдущие изменения сборки).
- После вызова деактивируйте, а затем снова вставьте объект State в дерево в другом месте.
Каркас заменяет поддерево под этим виджетом на виджет, возвращаемый этим методом, либо путем обновления существующего поддерева, либо путем удаления поддерева и надувания нового поддерева, в зависимости от того, может ли виджет, возвращенный этим методом, обновить корень существующего поддерева., как определено путем вызова Widget.canUpdate.
Обычно реализации возвращают вновь созданное созвездие виджетов, которые сконфигурированы с информацией из конструктора этого виджета, заданного BuildContext и внутреннего состояния этого объекта State.
@override
Widget build(BuildContext context, MyButtonState state) {
... () { print("color: $color"); } ...
}
6- didUpdateWidget (): - вызывается при изменении конфигурации виджета.
Если родительский виджет перестраивается и запрашивает, чтобы это местоположение в дереве обновлялось для отображения нового виджета с тем же типом среды выполнения и Widget.key, платформа обновит свойство виджета этого объекта State для ссылки на новый виджет, а затем вызовет это метод с предыдущим виджетом в качестве аргумента.
Переопределите этот метод для ответа при изменении виджета (например, для запуска неявной анимации).
Фреймворк всегда вызывает build после вызова didUpdateWidget, что означает, что любые вызовы setState в didUpdateWidget являются избыточными.
@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
7- setState (): - всякий раз, когда вы изменяете внутреннее состояние объекта State, вносите изменения в функцию, которую вы передаете setState
:
Вызов setState уведомляет платформу о том, что внутреннее состояние этого объекта изменилось таким образом, что это может повлиять на пользовательский интерфейс в этом поддереве, что заставит платформу запланировать сборку для
это государственный объект.Если вы просто измените состояние напрямую, не вызывая setState, каркас может не планировать сборку, а пользовательский интерфейс для этого поддерева может не обновляться для отражения нового состояния.
setState(() { _myState = newValue });
8- deactivate (): - Деактивация вызывается, когда State удаляется из дерева, но может быть повторно вставлена до завершения текущего изменения кадра. Этот метод существует в основном потому, что объекты состояния можно перемещать из одной точки дерева в другую.
- Каркас вызывает этот метод всякий раз, когда удаляет этот объект State из дерева. В некоторых случаях каркас будет повторно вставлять объект State в другую часть дерева (например, если поддерево, содержащее этот объект State, будет перенесено из одного места в дереве в другое). Если это произойдет, фреймворк будет вызывать сборку, чтобы дать объекту State возможность адаптироваться к новому положению в дереве. Если платформа повторно вставляет это поддерево, оно будет делать это до конца кадра анимации, в котором поддерево было удалено из дерева. По этой причине объекты State могут отложить высвобождение большинства ресурсов до тех пор, пока инфраструктура не вызовет их метод dispose.
Это редко используется.
@protected
@mustCallSuper
void deactivate() { }
9- dispose (): - вызывается, когда этот объект навсегда удален из дерева.
Фреймворк вызывает этот метод, когда этот объект State больше никогда не будет построен. После звонков рамки
dispose()
объект State считается несмонтированным, а свойство mount имеет значение false. На этом этапе вызывать setState является ошибкой. Эта стадия жизненного цикла является конечной: невозможно перемонтировать объект State, который был удален.Подклассы должны переопределить этот метод, чтобы освободить любые ресурсы, сохраненные этим объектом (например, остановить любые активные анимации).
@protected
@mustCallSuper
void dispose() {
assert(_debugLifecycleState == _StateLifecycle.ready);
assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
}
Для получения дополнительной информации перейдите сюда, здесь
Из документации на flutter.io:
... Важно отметить, что в основе виджеты без сохранения состояния и с сохранением состояния ведут себя одинаково. Они перестраивают каждый кадр, разница в том, что StatefulWidget имеет объект State, который хранит данные состояния между кадрами и восстанавливает их.
Если вы сомневаетесь, то всегда помните это правило: если виджет изменяется (например, пользователь взаимодействует с ним), он сохраняет состояние. Однако, если дочерний элемент реагирует на изменения, содержащийся родитель может по-прежнему быть виджетом без сохранения состояния, если родительский элемент не реагирует на изменения.
Как упомянуть в флаттерских документах
В чем смысл?
Некоторые виджеты с состоянием, а некоторые без состояния. Если виджет изменяется - например, с ним взаимодействует пользователь, - он сохраняет состояние. Состояние виджета состоит из значений, которые могут изменяться, например, текущее значение ползунка или флажок. Состояние виджета хранится в объекте State, отделяя состояние виджета от его внешнего вида. Когда состояние виджета изменяется, объект состояния вызывает setState(), сообщая платформе о перерисовке виджета.
Виджет без состояния не имеет внутреннего состояния для управления. Icon, IconButton и Text являются примерами виджетов без состояния, которые являются подклассами StatelessWidget.
Виджет с состоянием является динамическим. Пользователь может взаимодействовать с виджетом с отслеживанием состояния (например, вводя в форму или перемещая ползунок), или он меняется со временем (возможно, подача данных приводит к обновлению пользовательского интерфейса). Флажок, Радио, Слайдер, InkWell, Форма и TextField являются примерами виджетов с состоянием, которые являются подклассами StatefulWidget.
Я могу придумать очень простую аналогию. У вас есть мебель с книгами, украшениями и телевизором. Мебель без гражданства, она ничего не делает, не двигается. В телевизоре, с другой стороны, вы можете включать, выключать, переключать канал, воспроизводить фильм, если к нему подключен какой-либо DVD, и т. Д. У телевизора есть внутреннее состояние, которое влияет на его поведение. В мебели у вас нет гос. Наличие телевизора в мебели не добавляет ей изящества. Надеюсь это поможет.
Статические виджеты являются статическими виджетами. Вам просто нужно передать несколько свойств перед инициализацией виджетов без сохранения состояния. Они не зависят от изменений данных или поведения. Например. Text, Icon, RaisedButton - это виджеты без сохранения состояния.
Виджеты с отслеживанием состояния - это динамические виджеты, которые могут обновляться во время выполнения в зависимости от действий пользователя или изменения данных. Если виджет может изменить свое состояние во время выполнения, это будет виджет с сохранением состояния.
Изменить 15/11/2018
Виджет без сохранения состояния может быть повторно введен, если изменились входные / внешние данные. здесь внешние данные - это данные, которые передаются через конструктор.
Принимая во внимание, что виджет Statefull может переименоваться, если изменяются входные данные или изменяется состояние виджета.
Но виджеты без состояния не имеют никакого состояния, поэтому они будут отображаться один раз и не будут обновляться самостоятельно, а будут обновляться только при изменении внешних данных. И Statefull Widgets имеют внутреннее состояние.
У виджетов без состояния и состояния полный жизненный цикл.
При написании приложения вы обычно создаете новые виджеты, которые являются подклассами StatelessWidget или StatefulWidget.
Вот некоторые различия между StatelessWidget
а также StatefulWidget
Виджеты:
Виджет без сохранения состояния:
- Виджет, не требующий изменяемого состояния.
- Виджеты без сохранения состояния - это статические виджеты.
- Они не зависят от изменений данных или поведения.
- Виджеты без сохранения состояния не имеют состояния, они будут отображаться один раз и не будут обновляться, а будут обновляться только при изменении внешних данных.
- Например:
Text
,Icon
,RaisedButton
виджеты без сохранения состояния.
Виджет без сохранения состояния:
- Виджет с изменяемым состоянием.
- Виджеты с отслеживанием состояния - это динамические виджеты.
- Их можно обновлять во время выполнения в зависимости от действий пользователя или изменения данных.
- Виджеты с отслеживанием состояния имеют внутреннее состояние и могут повторно отрисовываться, если изменяются входные данные или состояние виджета.
- Например:
Checkbox
,Radio Button
,Slider
виджеты с отслеживанием состояния
Состояние - это информация, что (1) может быть прочитано синхронно при построении виджета, и (2) может измениться в течение времени жизни виджета. Ответственность за своевременное уведомление государства об изменении такого состояния несет разработчик виджетов, используя State.setState.
StatefulWidget:
Виджет с состоянием - это виджет, который описывает часть пользовательского интерфейса, создавая совокупность других виджетов, которые описывают пользовательский интерфейс более конкретно. Процесс построения продолжается рекурсивно, пока описание пользовательского интерфейса не станет полностью конкретным (например, полностью состоит из RenderObjectWidgets, которые описывают конкретные RenderObjects).
Виджет с отслеживанием состояния полезен, когда часть пользовательского интерфейса, который вы описываете, может динамически изменяться, например, из-за состояния, управляемого внутренними часами, или в зависимости от некоторого состояния системы. Для композиций, которые зависят только от информации о конфигурации в самом объекте и BuildContext, в котором виджет раздувается, рассмотрите возможность использования StatelessWidget.
Сами экземпляры StatefulWidget являются неизменяемыми и сохраняют свое изменяемое состояние либо в отдельных объектах State, созданных методом createState, либо в объектах, на которые подписывается это State, например объекты Stream или ChangeNotifier, ссылки на которые хранятся в конечных полях StatefulWidget сам.
StatelessWidget:
Виджет без сохранения состояния - это виджет, который описывает часть пользовательского интерфейса путем создания совокупности других виджетов, которые описывают пользовательский интерфейс более конкретно. Процесс построения продолжается рекурсивно, пока описание пользовательского интерфейса не станет полностью конкретным (например, полностью состоит из RenderObjectWidgets, которые описывают конкретные RenderObjects).
Виджет без сохранения состояния полезен, когда описываемая вами часть пользовательского интерфейса не зависит ни от чего, кроме информации о конфигурации в самом объекте и BuildContext, в котором виджет раздувается. Для композиций, которые могут динамически изменяться, например, из-за состояния, управляемого внутренними часами, или в зависимости от некоторого состояния системы, рассмотрите возможность использования StatefulWidget.
Stackru вопрос о сохранении состояния без сохранения состояния.
В Flutter отличие состоит в том, что виджеты без состояния могут быть определены только с помощью аргументов конструктора. Если вы создадите два виджета без сохранения состояния с использованием одинаковых аргументов, они будут одинаковыми.
Однако виджет с сохранением состояния не обязательно совпадает с другим, созданным с такими же аргументами конструктора. Это может быть в другом состоянии.
На самом деле виджет с сохранением состояния сам по себе неизменен (без сохранения состояния), но Flutter управляет отдельным объектом состояния и связывает его с виджетом, как объяснено в документе StatefulWidget. Это означает, что когда Flutter перестраивает виджет с сохранением состояния, он проверит, следует ли ему повторно использовать предыдущий объект состояния, и при желании присоединит этот объект состояния к виджету.
Родительский виджет не имеет состояния, потому что он не заботится о состоянии своего дочернего элемента. Сам ребенок с состоянием (или технически Флаттер) позаботится о своем собственном состоянии.
На высоком уровне, я согласен, что это делает родительский виджет с состоянием, потому что два родителя могут содержать двух дочерних элементов с разными состояниями и, таким образом, сами по себе технически различны. Но с точки зрения Flutter он создает родительский виджет, не заботясь о состоянии, и только при построении дочерний элемент будет учитывать его состояние.
Без сохранения состояния: состояние виджета создается ТОЛЬКО ОДИН РАЗ, затем он может обновлять значения, но не состояние явно. Это также видно из структуры. Вот почему у него есть только один класс, который расширяется с помощьюStatelessWidget
. Поэтому, если я скажу, они никогда не смогут повторно запуститьbuild()
снова метод.
С отслеживанием состояния: виджеты могут обновлять свое СОСТОЯНИЕ (локально) и значения несколько раз при срабатывании события. По этой причине реализация тоже разная. В этом у нас есть 2 класса, один из которыхStatefulWidget
а другой - это обработчик реализации состояния, т.е. State<YourWidget>
. Итак, если я скажу, они могут повторно запуститьbuild()
метод снова и снова на основе инициированных событий.
Схема ниже поможет.
Что такое виджеты с отслеживанием состояния и без состояния?
TL;DR: виджет, который позволяет обновлять экран, является виджетом с отслеживанием состояния. Виджет, который не имеет состояния.
Более подробно, динамический виджет с содержанием, которое может изменяться, должен быть виджетом с отслеживанием состояния. Виджет без сохранения состояния может изменять содержимое только при изменении параметров, и, следовательно, это необходимо делать выше точки его местоположения в иерархии виджетов. Экран или виджет, содержащий статический контент, должен быть виджетом без сохранения состояния, но для изменения содержимого он должен иметь состояние.
Я нашел это относительное содержание в интересном средстве массовой информации. Пожалуйста!
Простыми словами:
Как мы знаем, каждый виджет - это вид во флаттере. У которого есть свои классы. Когда мы используем эти классы, мы создаем из них объект. Мы даем значения их различным переменным / свойствам. Ex. Мы создаем текстовый виджет, поэтому можем присвоить ему String, Color, Font Size, Font family. Таким образом, давая это, мы определяем его свойства при его создании. До этого момента виджеты без сохранения состояния или с отслеживанием состояния были одинаковыми, но,
Когда мы хотим снова и снова изменять / обновлять его свойства (скажем, String или Color), тогда это должен быть виджет Stateful.
И когда мы не хотим изменять его свойства после определения в первый раз, это виджет без состояния.
это означает, что мы заботимся о данных, которые виджет хранит / контролирует / показывает.
Таким образом, Stateless - это меньше данных, а Stateful - это полные данные.
Теперь, если вы определяете класс, который не имеет состояния, это означает, что этот класс не заботится / имеет в нем переменные или говорит данные в своем собственном классе, то есть на уровне класса, но в нем может быть другой виджет / класс, который заботится о данных, т.е.. Так что это никак не влияет друг на друга.
Пожалуйста, поправьте меня, если я ошибаюсь.
отказ от ответственности:- начал работать над флаттером с прошлой недели:)
Виджет без состояния и с сохранением состояния имеет собственный жизненный цикл для создания и обновления пользовательского интерфейса. однако вы можете использовать либо без состояния, либо с полным состоянием для рендеринга пользовательского интерфейса, но практически без состояния удобнее, когда пользовательский интерфейс полностью или частично зависит от внешних данных (например, рендеринг списка с использованием api), тогда как использование виджета с полным состоянием для визуализации статического пользовательского интерфейса, как любой экран ввода, хорошая практика.
Что такое виджеты с отслеживанием состояния и без состояния?
Виджет без сохранения состояния: виджет без состояния создается только тогда, когда он имеет родительские изменения.
Виджеты с отслеживанием состояния: виджеты с полным состоянием содержат состояние виджета и могут быть перестроены при изменении состояния.