- 原文博客地址: Flutter中Widget的生命周期和渲染原理
- 之前的
Flutter
系列文章中都有介绍一些常用的Widget
这里就主要了解Flutter
的渲染原理和Widget
的生命周期
Flutter
中Widget
的生命周期
StatelessWidget
是通过构造函数(Constructor
)接收父Widget
直接传入值,然后调用build
方法来构建,整个过程非常简单- 而
StatefulWidget
需要通过State
来管理其数据,并且还要监控状态的改变决定是否重新build
整个Widget
- 这里主要讨论
StatefulWidget
的生命周期,就是它从创建到显示再到更新最后到销毁的整个过程 StatefulWidget
本身由两个类组成的:StatefulWidget
和State
- 在
StatefulWidget
中的相关方法主要就是- 执行
StatefulWidget
的构造函数(Constructor
)来创建出StatefulWidget
- 执行
StatefulWidget
的createState
方法,来创建一个维护StatefulWidget
的State
对象 - 所以我们探讨
StatefulWidget
的生命周期, 最终是探讨State
的生命周期
- 执行
- 那么为什么
Flutter
在设计的时候,StatefulWidget
的build
方法要放在State
中而不是自身呢- 首先
build
出来的Widget
是需要依赖State
中的变量(数据/自定义的状态)的 Flutter
在运行过程中,Widget
是不断的创建和销毁的, 当我们自己的状态改变时, 我们只希望刷新当前Widget
, 并不希望创建新的State
- 首先
上面图片大概列出了StatefulWidget
的简单的函数调用过程
constructor
调用createState
创建State
对象时, 执行State
类的构造方法(Constructor
)来创建State
对象
initState
initState
是StatefulWidget
创建完后调用的第一个方法,而且只执行一次- 类似于
iOS
的viewDidLoad
,所以在这里View
并没有完成渲染 - 我们可以在这个方法中执行一些数据初始化的操作,或者发送网络请求
@override
void initState() {
// 这里必须调用super的方法
super.initState();
print('4. 调用_HomeScreenState----initState');
}
- 这个方法是重写父类的方法,必须调用
super
,因为父类中会进行一些其他操作 - 另一点在源码中, 会看到这个方法中有一个
mustCallSuper
的注解, 这里就限制了必须调用父类的方法
@protected
@mustCallSuper
void initState() {
assert(_debugLifecycleState == _StateLifecycle.created);
}
didChangeDependencies
didChangeDependencies
在整个过程中可能会被调用多次, 但是也只有下面两种情况下会被调用
- 在
StatefulWidget
第一次创建的时候didChangeDependencies
会被调用一次, 会在initState
方法之后会被立即调用 - 从其他对象中依赖一些数据发生改变时, 比如所依赖的
InheritedWidget
状态发生改变时, 也会被调用
build
build
同样也会被调用多次- 在上述
didChangeDependencies
方法被调用之后, 会重新调用build
方法, 来看一下我们当前需要重新渲染哪些Widget
- 当每次所依赖的状态发生改变的时候
build
就会被调用, 所以一般不要将比较好使的操作放在build
方法中执行
didUpdateWidget
执行didUpdateWidget
方法是在当父Widget
触发重建时,系统会调用didUpdateWidget
方法
dispose
- 当前的
Widget
不再使用时,会调用dispose
进行销毁 - 这时候就可以在
dispose
里做一些取消监听、动画的操作 - 到这里, 也就意味着整个生命周期的过程也就结束了
setState
setState
方法可以修改在State
中定义的变量- 当我们手动调用
setState
方法,会根据最新的状态(数据)来重新调用build
方法,构建对应的Widgets
setState
内部其实是通过调用_element.markNeedsBuild();
实现更新Widget
整个过程的代码如下:
class HomeScreen extends StatefulWidget {
HomeScreen() {
print('1. 调用HomeScreen---constructor');
}
@override
_HomeScreenState createState() {
print('2. 调用的HomeScreen---createState');
return _HomeScreenState();
}
}
class _HomeScreenState extends State<HomeScreen> {
int _counter = 0;
_HomeScreenState() {
print('3. 调用_HomeScreenState----constructor');
}
@override
void initState() {
// 这里必须调用super的方法
super.initState();
print('4. 调用_HomeScreenState----initState');
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('调用_HomeScreenState----didChangeDependencies');
}
@override
Widget build(BuildContext context) {
print('5. 调用_HomeScreenState----build');
return Scaffold(
appBar: AppBar(title: Text('生命周期', style: TextStyle(fontSize: 20))),
body: Center(
child: Column(
children: <Widget>[
Text('当前计数: $_counter', style: TextStyle(fontSize: 20),),
RaisedButton(
child: Text('点击增加计数', style: TextStyle(fontSize: 20),),
onPressed: () {
setState(() {
_counter++;
});
}
)
],
),
),
);
}
@override
void dispose() {
super.dispose();
print('6. 调用_HomeScreenState---dispose');
}
}
打印结果如下:
flutter: 1. 调用HomeScreen---constructor
flutter: 2. 调用的HomeScreen---createState
flutter: 3. 调用_HomeScreenState----constructor
flutter: 4. 调用_HomeScreenState----initState
flutter: 调用_HomeScreenState----didChangeDependencies
flutter: 5. 调用_HomeScreenState----build
// 每次调用setState, 都会执行build
flutter: 5. 调用_HomeScreenState----build
flutter: 5. 调用_HomeScreenState----build
Flutter渲染原理
在Flutter
中渲染过程是通过Widget
, Element
和RenderObject
实现的, 下面是FLutter
中的三种树结构
Widget
这是Flutter
官网对Widget
的说明
Flutter widgets are built using a modern framework that takes inspiration from React. The central idea is that you build your UI out of widgets. Widgets describe what their view should look like given their current configuration and state. When a widget’s state changes, the widget rebuilds its description, which the framework diffs against the previous description in order to determine the minimal changes needed in the underlying render tree to transition from one state to the next.
Flutter
的Widgets
的灵感来自React
,中心思想是使用这些Widgets
来搭建自己的UI界面- 通过当前
Widgets
的配置和状态描述这个页面应该展示成什么样子 - 当一个
Widget
发生改变时,Widget
就会重新build
它的描述,框架会和之前的描述进行对比,来决定使用最小的改变在渲染树中,从一个状态到另一个状态 - 从这段说明中大概意思也就是
Widgets
只是页面描述层面的, 并不涉及渲染层面的东西, 而且如果所依赖的配置和状态发生变化的时候, 该Widgets
会重新build
- 而对于渲染对象来说, 只会使用最小的开销重新渲染发生改变的部分而不是全部重新渲染