The concept of life cycle
- What is the life cycle?
Lifecycle is basically a method function called back to let developers know what state the Widget is in
- What does it do?
- Listen for events in widgets
- Initializing data: Creating data and sending network requests
- Memory management: destroy data and listeners, destroy timers, etc
The Widget’s life cycle
- stateless
Stateless
-
- A constructor
-
- The build method
class SearchCell extends StatelessWidget {
// const SearchCell();
SearchCell(){
print('Constructor called');
};
@override
Widget build(BuildContext context) {
print('Build method called');
return Container();
}
Copy the code
- stateful
Stateful
Contains two objectsWidget
,State
)
-
- Constructor of a Widget
-
- The Widget
creatState
- The Widget
-
- Constructor of State
-
- The State of
initState
methods
- The State of
-
didChangeDependencies
Methods: Change the dependency, and the method is called when the InheritedWidget for the dependency (shared data) changes
-
- The State of
build
Method when calledsetState
Method, which recalls build to render
- The State of
-
- The State of
dispose
Method, called at destruction time
- The State of
class SearchPage extends StatefulWidget {
SearchPage(){
print('Widget constructor ');
}
@override
_SearchPageState createState() {
print('the Widget CreatState');
return_SearchPageState(); }}class _SearchPageState extends State<SearchPage> {
_SearchPageState() {
print('Constructor of State');
}
@override
void initState() {
// TODO: implement initState
super.initState();
print('State's initState method ');
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
print(Dispose method of State);
}
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
print('didChangeDependencies methods');
}
@override
Widget build(BuildContext context) {
print('State build method ');
returnContainer(); }}Copy the code
Use the Flutter Hot Restart
Use a Flutter Hot Reload
setState
Inside the method:
_element
The type of:StatefulElement? _element;
BuildContext get context {
assert(() {
if (_element == null) {
throw FlutterError(
'This widget has been unmounted, so the State no longer has a context (and should be considered defunct). \n'
'Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active.',); }return true; } ());return_element! ; } StatefulElement? _element;Copy the code
We can see that the _element is the current context, so this is why calling setState reconstructs the build.
context as StatefulElement;
context.markNeedsBuild();
Copy the code
The above two lines of code have the same effect as setState!
InheritedWidget
Data sharing
If data from A needs to be passed to B, we passed it in the constructor, and the didChangeDependencies method is called only once in the following example.
class InheritedDemo extends StatefulWidget {
const InheritedDemo({Key? key}) : super(key: key);
@override
_InheritedDemoState createState() => _InheritedDemoState();
}
class _InheritedDemoState extends State<InheritedDemo> {
int _count = 0;@override
Widget build(BuildContext context) {
return Column(
children: [
SizedBox(height: 200),
TextCount(count: _count),// _count is passed through the component's constructor
ElevatedButton(
onPressed: () {
_count++;
setState(() {});
},
child: Text('am I'), a)],); }}class TextCount extends StatefulWidget {
final int count;
TextCount({required this.count});
@override
_TextCountState createState() => _TextCountState();
}
class _TextCountState extends State<TextCount> {
@override
Widget build(BuildContext context) {
returnText(widget.count.toString()); }}Copy the code
[InheritedWidget] [InheritedWidget] [InheritedWidget] [InheritedWidget] [InheritedWidget] [InheritedWidget] [InheritedWidget] [InheritedWidget]
abstract class InheritedWidget extends ProxyWidget {
// The constructor of the parent class
const InheritedWidget({ Key? key, required Widget child })
: super(key: key, child: child);
@override
InheritedElement createElement() => InheritedElement(this);
@protected
bool updateShouldNotify(covariant InheritedWidget oldWidget);
}
Copy the code
-
- Start by defining a shared data class that inherits from the widget
-
- Secondly, implement the constructor, which can be referred to
InheritedWidget
Abstract the methods of the base class
- Secondly, implement the constructor, which can be referred to
-
- Finally, define a class method for external use to easily retrieve data
-
- Also choose to implement update data to notify widgets that rely on shared data
class MyData extends InheritedWidget {
final int count;
// constructor
const MyData({required this.count, required Widget child})
: super(child: child);
// Class methods are provided for external use to retrieve data
static MyData? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyData>();
}
// Whether to notify when data changes
@override
bool updateShouldNotify(MyData oldWidget) {
return oldWidget.count != count;
}
}
Copy the code
So how do you use it to associate data with components?
-
- Save and associate: Use the constructor in the build method to retrieve the data saved and associated with widgets that need to use that data
-
- Pull out: Call the class method to pull out the widget when it needs to be used
class _InheritedDemoState extends State<InheritedDemo> {
int _count = 0;
@override
Widget build(BuildContext context) {
return MyData( // Use it here
count: _count,
child: ....
);
}
}
class _TextCountState extends State<TextCount> {
@override
Widget build(BuildContext context) {
returnText(MyData.of(context)! .count.toString()); }@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
print('didChangeDependencies methods'); }}Copy the code
The didChangeDependencies method is called again every time you click on it
How widgets render
Not all of themWidget
Will be rendered independently! Only integratedRenderObjectWidget
Will be createdRenderObject
Object! inFlutter
In the rendering process, there are three important trees,Flutter
The engine is aimed atRender
Tree render!
-
Widget tree, Element tree, Render Tree: Each Widget creates an Element object. The creatElement method is implicitly called to add Element to the Element tree
RenderElement
StatefulElement
StatelessElement
-
RenderElement: Basically create a RenderObject (RenderObjectWidget widgets create RenderElement)
Fluter
Will be calledmount
Method to createRanderObject
object
-
StatefulElement inherits ComponentElement(StatefulWidget creates StatefulElement)
- Call the creatState method to create the State
- Assign the Widget to state
state._widget = widget;
- Call state’s build method and pass Element, which is itself
StatelessElement
Inherited:ComponentElement
(StatelessWidget
Will createStatelessElement
)- Stateless creates Element
- The Element creation then calls the mount method
- Mount calls the widget’s bulid method to render and passes the Element itself