Flutter에서 Stateful과 Stateless 위젯의 관계는 무엇입니까?
상태 저장 위젯은 수명 내에서 상태를 변경하는 모든 위젯으로 정의됩니다. 그러나 a 가 자신의 자식 중 하나로 a StatelessWidget
를 갖는 것은 매우 일반적인 관행입니다 StatefulWidget
. 자식 중 하나로 StatelessWidget
있으면 상태 저장이 되지 StatefulWidget
않습니까?
나는의 코드의 일부로 문서를 살펴 보았지만 어떻게을 자식으로 가질 수 있고 여전히 남아 StatelessWidget
있는지 알 수 없었다 .StatelessWidget
Statefulwidget
StatelessWidget
Flutter에서 Stateful과 Stateless 위젯의 관계와 차이점은 무엇입니까?
StatelessWidget은 결코 재 구축 자체 (하지만 외부 이벤트에서 수행 할 수 있습니다)에 의해. StatefulWidget는 할 수 있습니다. 그것이 황금률입니다.
그러나 모든 종류의 위젯은 언제든지 다시 칠할 수 있습니다 .
Stateless only는 모든 속성이 변경 불가능 하며 속성을 변경 하는 유일한 방법은 해당 위젯의 새 인스턴스를 만드는 것임을 의미합니다. 예를 들어 위젯 트리를 잠그지 않습니다.
그러나 자녀의 유형에 대해 신경 쓰지 마십시오. 그것은 당신에게 어떤 영향도 미치지 않습니다.
flutter.io 의 문서에서 :
... 여기서 주목해야 할 중요한 점은 Stateless 및 Stateful 위젯이 모두 동일하게 작동한다는 점입니다. 그들은 모든 프레임을 다시 빌드합니다. 차이점은 StatefulWidget에는 프레임 전체에 걸쳐 상태 데이터를 저장하고 복원하는 State 개체가 있다는 것입니다.
확실하지 않은 경우 항상 다음 규칙을 기억하십시오. 위젯이 변경되면 (예 : 사용자가 위젯과 상호 작용하는 경우) 상태 저장입니다. 그러나 자식이 변화에 반응하는 경우 부모가 변화에 반응하지 않는 경우 포함하는 부모는 여전히 Stateless 위젯이 될 수 있습니다.
StatefulWidget 대 StatelessWidget.
StatelessWidget :-변경 가능한 상태를 필요로하지 않는 위젯.
상태 비 저장 위젯은 사용자 인터페이스를보다 구체적으로 설명하는 다른 위젯 집합을 구축하여 사용자 인터페이스의 일부를 설명하는 위젯입니다. 빌드 프로세스는 사용자 인터페이스에 대한 설명이 완전히 구체화 될 때까지 반복적으로 계속됩니다 (예 : 구체적인 RenderObject를 설명하는 RenderObjectWidgets로 완전히 구성됨).
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 :-변경 가능한 상태를 가진 위젯.
- 상태 저장 위젯은 설명하는 사용자 인터페이스의 일부가 동적으로 변경 될 수있는 경우 유용합니다.
Flutter가를 빌드 StatefulWidget
하면 State 객체가 생성됩니다. 이 객체는 해당 위젯의 모든 변경 가능 상태가 유지되는 곳입니다.
상태의 개념은 다음 두 가지로 정의됩니다.
1) 위젯에서 사용하는 데이터가 변경 될 수 있습니다.
2) 위젯이 빌드 될 때 데이터를 동 기적으로 읽을 수 없습니다. (모든 상태는 빌드 메소드가 호출 될 때까지 설정되어야합니다).
StatefulWidget 수명주기
수명주기에는 다음과 같은 단순화 된 단계가 있습니다.
1- createState () :-Flutter가 StatefulWidget을 빌드하도록 지시하면 즉시 createState()
.
트리의 지정된 위치에서이 위젯의 변경 가능한 상태를 만듭니다.
하위 클래스는 연결된 State 하위 클래스의 새로 생성 된 인스턴스를 반환하려면이 메서드를 재정의해야합니다.
@override
_MyState createState() => _MyState();
2- mount == true :-모든 위젯에는 bool this.mounted 속성이 있습니다. buildContext
가 할당 되면 참 이됩니다. 위젯이 마운트 해제되었을 때 setState를 호출하는 것은 오류입니다. 이 State 개체가 현재 트리에 있는지 여부입니다.
State 객체를 생성 한 후를 호출하기 전에
initState
프레임 워크는 State 객체를
BuildContext
. State 객체는 프레임 워크가를
호출 할 때까지 마운트 된 상태로 유지되며 그dispose()
이후에는 프레임 워크가
State 객체에 다시 빌드를 요청하지 않습니다 .mount가 true가 아니면 setState를 호출하는 것은 오류입니다.
bool get mounted => _element != null;
3- initState () :-위젯이 생성 될 때 호출되는 첫 번째 메서드입니다 (물론 클래스 생성자 이후).
initState
한 번만 호출됩니다. 그것은 호출해야합니다super.initState().
위젯의 생성 된 인스턴스에 대해 특정 BuildContext에 의존하는 데이터를 초기화합니다.
트리에서 이러한 위젯 '부모'에 의존하는 속성을 초기화합니다.
ChangeNotifiers
이 위젯의 데이터를 변경할 수있는 Streams, 또는 기타 개체를 구독합니다 .
@override
initState() {
super.initState();
// Add listeners to this class
cartItemStream.listen((data) {
_updateWidget(data);
});
}
4- didChangeDependencies () :-이 State 객체의 종속성이 변경 될 때 호출됩니다.
이 메서드는 initState 직후에도 호출됩니다. 이 메서드에서 BuildContext.inheritFromWidgetOfExactType을 호출하는 것이 안전합니다.
프레임 워크는 종속성 변경 후 항상 빌드를 호출하기 때문에 서브 클래스는이 메서드를 거의 재정의하지 않습니다. 일부 서브 클래스는 종속성이 변경 될 때 비용이 많이 드는 작업 (예 : 네트워크 가져 오기)을 수행해야하고이 작업이 모든 빌드에 대해 수행하기에는 너무 비싸기 때문에이 메서드를 재정의합니다.
@protected
@mustCallSuper
void didChangeDependencies() { }
5- build () :-위젯이 나타내는 사용자 인터페이스의 일부를 설명합니다.
프레임 워크는 다양한 상황에서이 메서드를 호출합니다.
- initState를 호출 한 후.
- didUpdateWidget을 호출 한 후.
- setState에 대한 호출을받은 후.
- 이 State 개체의 종속성이 변경된 후 (예 : 이전 빌드 변경에서 참조 된 InheritedWidget).
- 비활성화를 호출 한 후 다른 위치의 트리에 State 개체를 다시 삽입합니다.
프레임 워크는이 메서드에서 반환 된 위젯이 기존 하위 트리의 루트를 업데이트 할 수 있는지 여부에 따라 기존 하위 트리를 업데이트하거나 하위 트리를 제거하고 새 하위 트리를 확장하여이 위젯 아래의 하위 트리를이 메서드에서 반환 된 위젯으로 바꿉니다. , Widget.canUpdate를 호출하여 결정됩니다.
일반적으로 구현은이 위젯의 생성자, 지정된 BuildContext 및이 State 객체의 내부 상태의 정보로 구성된 새로 생성 된 위젯 집합을 반환 합니다.
@override
Widget build(BuildContext context, MyButtonState state) {
... () { print("color: $color"); } ...
}
6- didUpdateWidget () :-위젯 구성이 변경 될 때마다 호출됩니다.
상위 위젯이 동일한 런타임 유형 및 Widget.key를 가진 새 위젯을 표시하도록 트리의이 위치 업데이트를 다시 빌드하고 요청하면 프레임 워크는이 State 개체의 위젯 속성을 업데이트하여 새 위젯을 참조한 다음이를 호출합니다. 이전 위젯을 인수로 사용하는 메서드.
위젯이 변경 될 때 (예 : 암시 적 애니메이션 시작) 응답하도록이 메서드를 재정의합니다.
프레임 워크는 항상 didUpdateWidget을 호출 한 후 build를 호출합니다. 즉, didUpdateWidget의 setState에 대한 모든 호출이 중복됩니다.
@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
7- setState () : -State 객체의 내부 상태를 변경할 때마다 전달하는 함수를 변경합니다 setState
.
setState를 호출 하면이 하위 트리의 사용자 인터페이스에 영향을 줄 수있는 방식으로이 개체의 내부 상태가 변경되었음을 프레임 워크에 알립니다. 이로 인해 프레임 워크는
이 State 개체에 대한 빌드를 예약 합니다.setState 를 호출하지 않고 상태를 직접 변경하면 프레임 워크가 빌드를 예약하지 않을 수 있으며이 하위 트리의 사용자 인터페이스가 새 상태를 반영하도록 업데이트되지 않을 수 있습니다.
setState(() { _myState = newValue });
8- deactivate () :-Deactivate는 State가 트리에서 제거 될 때 호출되지만 현재 프레임 변경이 완료되기 전에 다시 삽입 될 수 있습니다. 이 방법은 기본적으로 State 객체를 트리의 한 지점에서 다른 지점으로 이동할 수 있기 때문에 존재합니다.
- The framework calls this method whenever it removes this State object from the tree. In some cases, the framework will reinsert the State object into another part of the tree (e.g., if the subtree containing this State object is grafted from one location in the tree to another). If that happens, the framework will ensure that it calls build to give the State object a chance to adapt to its new location in the tree. If the framework does reinsert this subtree, it will do so before the end of the animation frame in which the subtree was removed from the tree. For this reason, State objects can defer releasing most resources until the framework calls their dispose method.
This is rarely used.
@protected
@mustCallSuper
void deactivate() { }
9-dispose():--Called when this object is removed from the tree permanently.
The framework calls this method when this State object will never build again. After the framework calls
dispose()
, the State object is considered unmounted and the mounted property is false. It is an error to call setState at this point. This stage of the lifecycle is terminal: there is no way to remount a State object that has been disposed of.Subclasses should override this method to release any resources retained by this object (e.g., stop any active animations).
@protected
@mustCallSuper
void dispose() {
assert(_debugLifecycleState == _StateLifecycle.ready);
assert(() { _debugLifecycleState = _StateLifecycle.defunct; return true; }());
}
For more info go here here, here
State is information that (1) can be read synchronously when the widget is built and (2) might change during the lifetime of the widget. It is the responsibility of the widget implementer to ensure that the State is promptly notified when such state changes, using State.setState.
StatefulWidget:
A stateful widget is a widget that describes part of the user interface by building a constellation of other widgets that describe the user interface more concretely. The building process continues recursively until the description of the user interface is fully concrete (e.g., consists entirely of RenderObjectWidgets, which describe concrete RenderObjects).
Stateful widget are useful when the part of the user interface you are describing can change dynamically, e.g. due to having an internal clock-driven state, or depending on some system state. For compositions that depend only on the configuration information in the object itself and the BuildContext in which the widget is inflated, consider using StatelessWidget.
StatefulWidget instances themselves are immutable and store their mutable state either in separate State objects that are created by the createState method, or in objects to which that State subscribes, for example Stream or ChangeNotifier objects, to which references are stored in final fields on the StatefulWidget itself.
StatelessWidget:
A stateless widget is a widget that describes part of the user interface by building a constellation of other widgets that describe the user interface more concretely. The building process continues recursively until the description of the user interface is fully concrete (e.g., consists entirely of RenderObjectWidgets, which describe concrete RenderObjects).
Stateless widget are useful when the part of the user interface you are describing does not depend on anything other than the configuration information in the object itself and the BuildContext in which the widget is inflated. For compositions that can change dynamically, e.g. due to having an internal clock-driven state, or depending on some system state, consider using StatefulWidget.
As mention in flutter docs
What’s the point?
Some widgets are stateful, and some are stateless. If a widget changes—the user interacts with it, for example—it’s stateful. A widget’s state consists of values that can change, like a slider’s current value or whether a checkbox is checked. A widget’s state is stored in a State object, separating the widget’s state from its appearance. When the widget’s state changes, the state object calls setState(), telling the framework to redraw the widget.
A stateless widget has no internal state to manage. Icon, IconButton, and Text are examples of stateless widgets, which subclass StatelessWidget.
A stateful widget is dynamic. The user can interact with a stateful widget (by typing into a form, or moving a slider, for example), or it changes over time (perhaps a data feed causes the UI to update). Checkbox, Radio, Slider, InkWell, Form, and TextField are examples of stateful widgets, which subclass StatefulWidget.
https://flutter.io/tutorials/interactive/#stateful-stateless
StackOverflow question on statefulness vs statelessness.
In Flutter, the difference is that stateless widgets can be defined by all the constructor arguments alone. If you create two stateless widgets using the same arguments, then they will be the same.
A stateful widget, however, is not necessarily the same as another built with the same constructor arguments. It might be in a different state.
Actually, a stateful widget is immutable (stateless) itself, but Flutter manages a separate state object and associates that with the widget, as explained in the StatefulWidget doc. This means that when Flutter rebuilds a stateful widget, it will check to see if it should reuse a previous state object and will, if desired, attach that state object to the widget.
The parent widget is stateless because it does not care about its child's state. The stateful child itself (or technically Flutter) will take care of its own state.
On a high level, I agree that this makes the parent widget stateful, because two parents might contain two childs with different states and thus be technically different themselves. But from the viewpoint of Flutter, it builds the parent widget without caring about the state and only when building the child will consider its statefullness.
Stateless Widgets are static widgets. You just need to pass few properties before initializing Stateless Widgets. They do not depend on any data change or any behavior change. For Example. Text, Icon, RaisedButton are Stateless Widgets.
Stateful Widgets are dynamic widgets, they can be updated during runtime based on user action or data change. If a Widget can change its state during run time it will be stateful widget.
Edit 15/11/2018
Stateless Widgets can re-render if the input/external data changed (external data being data that is passed through the constructor). Because Stateless Widgets do not have a state, they will be rendered once and will not update themselves, but will only be updated when external data changes.
Whereas Stateful Widgets have an internal state and can re-render if the input data changes or if Widget's state changes.
Both stateless and stateful widgets have different lifecycle.
'programing' 카테고리의 다른 글
Laravel 5.1을 5.2로 업그레이드하는 동안 치명적인 오류 (0) | 2021.01.18 |
---|---|
Redux에 여러 미들웨어를 추가하는 방법은 무엇입니까? (0) | 2021.01.18 |
C # 클래스에서 데이터베이스 테이블을 생성하려면 어떻게해야합니까? (0) | 2021.01.18 |
ASP.NET MVC 응용 프로그램 내에서 "실제"HttpContext를 어떻게 얻을 수 있습니까? (0) | 2021.01.18 |
XAML 요소에서 StringFormat을 사용하는 방법은 무엇입니까? (0) | 2021.01.18 |