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 - วิดเจ็ตที่มีสถานะไม่แน่นอน
- วิดเจ็ตสถานะมีประโยชน์เมื่อส่วนของอินเทอร์เฟซผู้ใช้ที่คุณกำลังอธิบายสามารถเปลี่ยนแปลงได้แบบไดนามิก
เมื่อ Flutter สร้าง a StatefulWidget
มันจะสร้างวัตถุสถานะ อ็อบเจ็กต์นี้เป็นที่ซึ่งสถานะที่เปลี่ยนแปลงได้ทั้งหมดสำหรับวิดเจ็ตนั้นถูกเก็บไว้
แนวคิดของรัฐถูกกำหนดโดยสองสิ่ง:
1) ข้อมูลที่วิดเจ็ตใช้อาจมีการเปลี่ยนแปลง
2) ไม่สามารถอ่านข้อมูลพร้อมกันได้เมื่อสร้างวิดเจ็ต (สถานะทั้งหมดจะต้องถูกกำหนดขึ้นตามเวลาที่เรียกวิธีการสร้าง)
วงจรชีวิต StatefulWidget
วงจรชีวิตมีขั้นตอนที่เรียบง่ายดังต่อไปนี้:
- createState () - เมื่อกระพือปีกได้รับคำสั่งให้สร้าง StatefulWidget
createState()
ทันทีเรียก
@override
_MyState createState() => _MyState();
- Mount == true - วิดเจ็ตทั้งหมดมี
this.mounted
คุณสมบัติบูล จะกลายเป็นจริงเมื่อbuildContext
มีการกำหนด เป็นข้อผิดพลาดในการโทรsetState
เมื่อยกเลิกการต่อเชื่อมวิดเจ็ต ว่าวัตถุสถานะนี้อยู่ในต้นไม้หรือไม่
หลังจากสร้างออบเจ็กต์สถานะและก่อนการเรียกinitState
ใช้เฟรมเวิร์กจะ "เมานต์" อ็อบเจ็กต์ State โดยเชื่อมโยงกับ
BuildContext
. อ็อบเจ็กต์สถานะยังคงถูกเมาท์จนกว่าเฟรมเวิร์กจะ
เรียกใช้dispose()
หลังจากนั้นเฟรมเวิร์กจะไม่ขอให้
อ็อบเจ็กต์สถานะสร้างอีก
เป็นข้อผิดพลาดในการเรียกใช้ setState เว้นแต่ว่าเมาท์จะเป็นจริง
bool get mounted => _element != null;
- initState () - นี่เป็นวิธีแรกที่เรียกว่าเมื่อสร้างวิดเจ็ต (หลังจากตัวสร้างคลาสแน่นอน)
initState
ถูกเรียกครั้งเดียวและครั้งเดียว มันต้องโทรsuper.initState().
เริ่มต้นข้อมูลที่อาศัย BuildContext เฉพาะสำหรับอินสแตนซ์ที่สร้างขึ้นของวิดเจ็ต
เริ่มต้นคุณสมบัติที่ขึ้นอยู่กับ 'parent' ของวิดเจ็ตเหล่านี้ในแผนภูมิ
สมัครสมาชิกสตรีมChangeNotifiers
หรือวัตถุอื่น ๆ ที่สามารถเปลี่ยนแปลงข้อมูลบนวิดเจ็ตนี้
@override
initState() {
super.initState();
cartItemStream.listen((data) {
_updateWidget(data);
});
}
- didChangeDependencies () - เรียกเมื่อการอ้างอิงของวัตถุสถานะนี้เปลี่ยนแปลง
วิธีนี้เรียกว่าทันทีหลังจากinitState
นั้น สามารถโทรBuildContext.inheritFromWidgetOfExactType
จากวิธีนี้ได้อย่างปลอดภัย
คลาสย่อยมักจะไม่แทนที่วิธีนี้เนื่องจากเฟรมเวิร์กจะเรียก build หลังจากการเปลี่ยนแปลงการอ้างอิงเสมอ คลาสย่อยบางคลาสจะแทนที่เมธอดนี้เนื่องจากต้องทำงานที่มีราคาแพงบางอย่าง (เช่นการดึงข้อมูลเครือข่าย) เมื่อการอ้างอิงเปลี่ยนไปและงานนั้นจะมีราคาแพงเกินไปที่จะทำสำหรับทุกบิลด์
@protected
@mustCallSuper
void didChangeDependencies() { }
- build() -- Describes the part of the user interface represented by the widget.
The framework calls this method in a number of different situations:
- After calling
initState
.
- After calling
didUpdateWidget
.
- After receiving a call to
setState
.
- After a dependency of this State object changes (e.g., an InheritedWidget referenced by the previous build changes).
- After calling deactivate and then reinserting the State object into the tree at another location.
The framework replaces the subtree below this widget with the widget returned by this method, either by updating the existing
subtree or by removing the subtree and inflating a new subtree,
depending on whether the widget returned by this method can update the
root of the existing subtree, as determined by calling
Widget.canUpdate
.
Typically implementations return a newly created constellation of widgets that are configured with information from this widget's
constructor, the given BuildContext, and the internal state of
this State object.
@override
Widget build(BuildContext context, MyButtonState state) {
... () { print("color: $color"); } ...
}
- didUpdateWidget() -- Called whenever the widget configuration changes.
If the parent widget rebuilds and request that this location in the tree update to display a new widget with the same runtime type and
Widget.key, the framework will update the widget property of this
State object to refer to the new widget and then call this method with
the previous widget as an argument.
Override this method to respond when the widget changes (e.g., to start implicit animations).
The framework always calls build after calling didUpdateWidget, which means any calls to setState in didUpdateWidget are redundant.
@mustCallSuper
@protected
void didUpdateWidget(covariant T oldWidget) { }
- setState() -- Whenever you change the internal state of a State object, make the change in a function that you pass to
setState
:
Calling setState notifies the framework that the internal state of this object has changed in a way that might impact the user interface
in this subtree, which causes the framework to schedule a build for
this State object.
If you just change the state directly without calling setState, the framework might not schedule a build and the user interface for this subtree might not be updated to reflect the new state.
setState(() { _myState = newValue });
- deactivate() -- Deactivate is called when State is removed from the tree, but it might be reinserted before the current frame change is finished. This method exists basically because State objects can be moved from one point in a tree to another.
- 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() { }
- 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