About Widget
concept
Flutter almost all objects are a Widget, the Widget Flutter concept broader, it can not only represent UI elements, it may also represent a number of functional components, such as: means for detecting a gesture of the GestureDetector
widget, for APP theme data transfer the Theme
so forth,
widget and Element
- Widget is actually
Element
the configuration data, Widget configuration tree is actually a tree, and the tree is the real UI rendered by theElement
constitution; however, asElement
is generated by Widget, so there is correspondence between them, in most scenes, we Widget can be broadly considered the tree refers to a tree or UI UI controls render tree. - Widget object may correspond to a plurality of
Element
objects. This is well understood, in accordance with a configuration (Widget), you can create multiple instances (Element).
Widget main window
@immutable
abstract class Widget extends DiagnosticableTree {
const Widget({ this.key });
final Key key;
@protected
Element createElement();
@override
String toStringShort() {
return key == null ? '$runtimeType' : '$runtimeType-$key';
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
}
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
}
Widget
Class inherits fromDiagnosticableTree
,DiagnosticableTree
namely "diagnostic tree", the main role is to provide debugging information.Key
: Thiskey
attribute is similar to React / Vue in thekey
main role is to decide whether the nextbuild
time multiplexing old widget, the conditions in the decisioncanUpdate()
process.createElement()
: As mentioned earlier, "may correspond to a plurality of WidgetElement
"; Flutter Framework UI when building the tree, will call this method to generate a corresponding nodeElement
object. This method is called Flutter Framework implicit in our development process basically does not call into.debugFillProperties(...)
Replication method of the parent class, mainly to set the diagnosis of some of the features tree.canUpdate(...)
Is a static method, it is mainly used in the Widget tree againbuild
when reuse old widget, in fact, specifically, should be: whether with a new Widget object to update the old UI tree correspondingElement
configuration object; through its source code we can see, as long asnewWidget
witholdWidget
theruntimeType
andkey
will use simultaneously equalnewWidget
to update theElement
configuration objects, otherwise it will create a newElement
.
StatelessWidget
Role: the scene does not need to maintain state, which is usually build
constructed by a nested UI Widget other methods, the build process would be to build their nested recursive Widget.
Inherited from Widget
class, override the createElement()
method:
@override
StatelessElement createElement() => new StatelessElement(this);
Context
context is BuildContext
an instance of a class, represents a context of the current widget in the widget tree, each corresponding to a widget will be a context object (widget is a widget because each node of a tree).
StatefulWidget
StatefulWidget is inherited from the Widget class, and rewriting the createElement () method, the difference is not the same as Element object returned; StatefulWidget further adds a new class interface createState ()
abstract class StatefulWidget extends Widget {
const StatefulWidget({ Key key }) : super(key: key);
@override
StatefulElement createElement() => new StatefulElement(this);
@protected
State createState();
}
StatefulElement
Indirect inherited fromElement
class with corresponding StatefulWidget (as configuration data).StatefulElement
It may be called multiple timescreateState()
to create the state (State) objects.createState()
And Stateful widget for creating state-related, it may be called multiple times in the Stateful widget's life cycle. For example, when a plurality of positions simultaneously inserted into the Stateful widget widget tree, Flutter framework will call this method for each location to generate a separate State instances, in fact, essentially aStatefulElement
corresponds to a State example.
state Lifecycle
import 'package:flutter/material.dart';
void main() => runApp(CounterWidget(
initValue: 10,
));
class CounterWidget extends StatefulWidget {
final int initValue;
const CounterWidget({Key key, this.initValue});
@override
_CounterWidgetState createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _counter;
/**
* 第一次被调用
*/
@override
void initState() {
super.initState();
//初始化状态
_counter = widget.initValue;
print("生命周期:initState");
}
@override
Widget build(BuildContext context) {
print("生命周期:build");
return MaterialApp(
title: "计数器",
home: Scaffold(
appBar: AppBar(
title: Text("计数器"),
),
body: Center(
child: FlatButton(
child: Text("$_counter"),
//点击后计数器自增
onPressed: () => setState(() => ++_counter),
),
),
),
);
}
//在新旧widget的key和runtimeType同时相等时didUpdateWidget()就会被调用
@override
void didUpdateWidget(CounterWidget oldWidget) {
super.didUpdateWidget(oldWidget);
print("生命周期:didUpdateWidget");
}
//state对象从树中被移除时调用
@override
void deactivate() {
super.deactivate();
print("生命周期:deactivate");
}
//state对象从树中被永久移除时调用
//通常用来回收和释放资源
@override
void dispose() {
super.dispose();
print("生命周期:dispose");
}
//只有热重载时候会调用
@override
void reassemble() {
super.reassemble();
print("生命周期:reassemble");
}
//依赖对象发生变化时被调用
@override
void didChangeDependencies() {
super.didChangeDependencies();
print("生命周期:didChangeDependencies");
}
}
Gets State Widget objects in the tree, and call SnackBar two ways
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "获取State对象",
home: Scaffold(
appBar: AppBar(
title: Text("获取State对象"),
),
body: GetState(),
),
);
}
}
class GetState extends StatefulWidget {
@override
_GetStateState createState() => _GetStateState();
}
class _GetStateState extends State<GetState> {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: <Widget>[
Builder(
builder: (context) {
return RaisedButton(
onPressed: () {
// 查找父级最近的Scaffold对应的ScaffoldState对象
ScaffoldState _scaffoldState =
context.ancestorStateOfType(TypeMatcher<ScaffoldState>());
//调用ScaffoldState的showSnackBar来弹出SnackBar
_scaffoldState.showSnackBar(
SnackBar(
content: Text("我是SnackBar"),
),
);
},
child: Text("点击显示SnackBar"),
);
},
),
Builder(
builder: (context) {
return RaisedButton(
onPressed: () {
// 直接通过of静态方法来获取ScaffoldState
ScaffoldState _scaffoldState =
Scaffold.of(context);
//调用ScaffoldState的showSnackBar来弹出SnackBar
_scaffoldState.showSnackBar(
SnackBar(
content: Text("我是SnackBar"),
),
);
},
child: Text("点击显示SnackBar"),
);
},
),
],
)
);
}
}
By GlobalKey
acquiring State
objects
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
//定义
static GlobalKey<ScaffoldState> _globalKey = GlobalKey();
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "获取State对象",
home: Scaffold(
key: _globalKey, //设置key
appBar: AppBar(
title: Text("获取State对象"),
),
body: Center(
child: Column(
children: <Widget>[
Builder(
builder: (context) {
return RaisedButton(
onPressed: () {
// 查找父级最近的Scaffold对应的ScaffoldState对象
_globalKey.currentState.openDrawer();
},
child: Text("点击显示SnackBar"),
);
},
),
],
)),
),
);
}
}