Introduction of the Widget
The Widget Describes the configuration for an [Element], the structure of the Flutter. And is an immutable description that will be associated with Element later.
The contents of the widget-Element-RenderObject trees will be sorted later
There are three priorities:
- A Widget is an immutable configuration information
- The Widget will be associated
Element
type - Abstract class that actually inherits subclasses during development:
StatefulWidget
.StatelessWidget
. StatefulWidget
The mutable state of is completely dependent on the associatedState
abstract class Widget extends DiagnosticableTree {
const Widget({ this.key });
final Key key;
@protected
ElementcreateElement(); ./// Whether the `newWidget` can be used to update an [Element] that currently
/// has the `oldWidget` as its configuration.
static bool canUpdate(Widget oldWidget, Widget newWidget) {
returnoldWidget.runtimeType == newWidget.runtimeType && oldWidget.key == newWidget.key; }}Copy the code
StatelessWidget
Life cycle of
StatelessWidget as a StatelessWidget, the lifecycle is simple:
const StatelessWidget({ Key? key }) : super(key: key);
The constructorStatelessElement createElement() => StatelessElement(this);
The Element associated with the Widget,Widget build(BuildContext context);
instructionsThe framework calls this method when this widget is inserted into the tree
//Element will only have widgets inside
/// An [Element] that uses a [StatelessWidget] as its configuration.
class StatelessElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
StatelessElement(StatelessWidget widget) : super(widget);
/// use
@override
StatelessWidget get widget => super.widget as StatelessWidget;
@override
Widget build() => widget.build(this);
@override
void update(StatelessWidget newWidget) {
super.update(newWidget);
_dirty = true; rebuild(); }}Copy the code
StatefulWidget
Life cycle of
A StatefulWidget is a StatefulWidget with the following lifecycle of the State associated with it:
- widget:
const StatefulWidget({ Key? key }) : super(key: key);
- widget:
StatefulElement createElement() => StatefulElement(this);
- widget:
State createState()
- state:
constructor
- state:
initState
- state:
didChangeDependencies
(ifInheritedWidget.rebuild
= >child.didChangeDependencies
) - state:
Widget build(BuildContext context);
(setState()
= >didUpdateWidget
= >build
) - The state:
Widget - Element
jointree
In the - state:
deactivate
- state:
dispose
- will
Element
removetrue
- InheritedWidget is called in childNode when the InheritedWidget method is rebuilt
didChangeDependencies
- When the setState() method is called
didUpdateWidget
Method, and then callbuild
Several key elements in the above process:
- in
StatefulWidget
In the callcreateElement()
Method, the key content:
// StatefulWidget is called when the Widget is mounted to the tree
StatefulElement createElement() {
// Element's constructor
return StatefulElement(this);
}
/// Creates an element that uses the given widget as its configuration.
/// Element constructor
/// 1.The widget.creatEstate () method is actively called and created_state!!!
/// 2. Then, hold the Element and widget in State
StatefulElement(StatefulWidget widget): _state = widget.createState(), super(widget) {
...
state._element = this;
state._widget = widget;
}
Copy the code
-
In createState(), it may be called multiple times. For example, if the widget is inserted into the tree in multiple locations, the framework will create a separate [State] object for each location
-
SetState implementation with dirty Element tags and updates:
/// Methods in State void setState(VoidCallback fn) { // 先调用 fn() ... final Object? result = fn() as dynamic; _element! .markNeedsBuild(); }/// Methods in Element /// Marks the element as dirty and adds it to the global list of widgets to /// rebuild in the next frame. /// /// Since it is inefficient to build an element twice in one frame, /// applications and widgets should be structured so as to only mark /// widgets dirty during event handlers before the frame begins, not during /// the build itself. void markNeedsBuild() { ... _dirty = true; // Just marking Element is added to the global Dirty list, which is updated the next frame through the loopowner! .scheduleBuildFor(this); // Owner is set by the parent. Owner passed in when mount is called } // BuildOwner class -- a management class in the Framework /// Adds an element to the dirty elements list so that it will be rebuilt /// when [WidgetsBinding.drawFrame] calls [buildScope]. void scheduleBuildFor(Element element) { ... _dirtyElements.add(element); // Add element to the global dirty list element._inDirtyList = true; } Copy the code