生命周期
StatefulWidget 生命周期
- 执行顺序,从上往下
名称 | 说明 |
---|---|
createState | 创建 State 只执行 1 次 |
initState | 初始 State, mounted 等于 true, 只执行 1 次 |
didChangeDependencies | 父或祖先 widget 中的 InheritedWidget 改变时会被调用 |
build | UI 被重新渲染的时候多次执行 |
addPostFrameCallback | 渲染结束回调,只执行 1 次 |
didUpdateWidget | 父类 setState 后,子类就会触发 |
deactivate | 从组件树中移除 State 时调用 |
dispose | 组件被释放时调用 |
不要再 build 里面更新状态, 影响性能
- initState 初始状态数据
void initState() {
super.initState();
print("initState");
}
- build 渲染视图,可多次
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () {
},
child: const Text("切换图片"),
),
imageWidget(
imgUrl: imgUrl ?? img1,
),
],
);
}
- mounted 状态
flutter 分配完你的组件树位置,会设置 mounted
为 true
。
你需要在 mounted == true
情况下,调用 setState()
来更新 UI ,这才是安全的操作。
ElevatedButton(
onPressed: () {
if (mounted == true) {
setState(() {
imgUrl = imgUrl == img1 ? img2 : img1;
});
}
},
child: const Text("切换图片"),
),
- didChangeDependencies
父或祖先 widget 中的 InheritedWidget 改变时会被调用。
InheritedWidget
和 React 中的 context 功能类似,和逐级传递数据相比,它们能实现组件跨级传递数据。这种从根开始向下传递数据的方式,很适合做全局数据的管理,如样式、基础数据等。
// 父或祖先widget中的InheritedWidget改变时会被调用
void didChangeDependencies() {
super.didChangeDependencies();
print("didChangeDependencies");
}
- didUpdateWidget
父类 setState 后,子类就会触发
// 父类 setState 后,子类就会触发
void didUpdateWidget(oldWidget) {
super.didUpdateWidget(oldWidget);
print("didUpdateWidget");
}
- addPostFrameCallback
渲染结束回调,只执行 1 次
如我们可以放在 initState 时设置
// 初始 State, mounted 等于 true, 只执行1次
void initState() {
super.initState();
print("initState");
// 渲染结束调用,只执行1次
SchedulerBinding.instance?.addPostFrameCallback((timeStamp) {
print("addPostFrameCallback");
print(timeStamp);
});
}
- deactivate
从组件树中移除 State 时调用
void deactivate() {
super.deactivate();
print("deactivate");
}
- dispose
组件被释放时调用
void dispose() {
print("dispose");
super.dispose();
}
- 代码
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
void main() {
runApp(const MyApp());
}
const img1 =
"https://ducafecat.tech/2021/12/09/blog/2021-jetbrains-fleet-vs-vscode/2021-12-09-10-30-00.png";
const img2 =
"https://ducafecat.tech/2021/12/09/blog/2021-jetbrains-fleet-vs-vscode/2021-12-09-20-45-02.png";
Widget imageWidget({required String imgUrl}) {
return Container(
padding: const EdgeInsets.all(10),
color: Colors.amber,
child: Image.network(imgUrl),
);
}
class BannerWidget extends StatefulWidget {
const BannerWidget({Key? key}) : super(key: key);
// 创建 State 只执行1次
State<BannerWidget> createState() {
print("createState");
return _BannerWidgetState();
}
}
class _BannerWidgetState extends State<BannerWidget> {
String? imgUrl;
// 初始 State, mounted 等于 true, 只执行1次
void initState() {
super.initState();
print("initState");
// 渲染结束调用,只执行1次
SchedulerBinding.instance?.addPostFrameCallback((timeStamp) {
print("addPostFrameCallback");
print(timeStamp);
});
}
// 父或祖先widget中的InheritedWidget改变时会被调用
void didChangeDependencies() {
super.didChangeDependencies();
print("didChangeDependencies");
}
// 父类 setState 后,子类就会触发
void didUpdateWidget(oldWidget) {
super.didUpdateWidget(oldWidget);
print("didUpdateWidget");
}
// 从组件树中移除 State 时调用
void deactivate() {
super.deactivate();
print("deactivate");
}
// 组件被释放时调用
void dispose() {
print("dispose");
super.dispose();
}
// UI 被重新渲染的时候多次执行
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () {
if (mounted == true) {
setState(() {
imgUrl = imgUrl == img1 ? img2 : img1;
});
}
},
child: const Text("切换图片"),
),
imageWidget(
imgUrl: imgUrl ?? img1,
),
],
);
}
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: const [
Text('有无状态组件'),
BannerWidget(),
],
),
),
debugShowCheckedModeBanner: false,
);
}
}
- 输出
flutter: createState
flutter: initState
flutter: didChangeDependencies
flutter: addPostFrameCallback
flutter: 0:00:00.000000
StatelessWidget 生命周期
无状态组件,不需要处理生命周期,直接显示即可
abstract class StatelessWidget extends Widget {
/// Initializes [key] for subclasses.
const StatelessWidget({ Key? key }) : super(key: key);
/// Creates a [StatelessElement] to manage this widget's location in the tree.
///
/// It is uncommon for subclasses to override this method.
StatelessElement createElement() => StatelessElement(this);
在源码中可见
createElement()
创建组件到组件树,不需要重写去维护
App 生命周期
- 第一步: 创建 StatefulWidget 组件,混入 WidgetsBindingObserver
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
...
- 第二步:添加观察者 addObserver
void initState() {
super.initState();
WidgetsBinding.instance?.addObserver(this); //添加观察者
}
- 生命周期变化时回调 didChangeAppLifecycleState
// 生命周期变化时回调
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
print("didChangeAppLifecycleState: $state");
}
名称 | 说明 |
---|---|
resumed | 应用程序可见且响应用户输入。 |
inactive | 应用程序处于非激活状态,无法响应用户输入。 |
pause | 应用程序不可见且无法响应用户输入,运行在后台。 |
detached | 应用程序仍寄存在 Flutter 引擎上,但与平台 View 分离。 |
suspending | 应用被挂起,此状态 IOS 永远不会回调 |
- 代码
import "package:flutter/material.dart";
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
_MyAppState createState() => _MyAppState();
}
//实现WidgetsBindingObserver观察者
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
void initState() {
super.initState();
WidgetsBinding.instance?.addObserver(this); //添加观察者
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("App生命周期"),
),
body: Column(
children: <Widget>[
const Text("首页"),
],
),
),
);
}
// 生命周期变化时回调
// resumed:应用可见并可响应用户操作,app进入前台
// inactive:用户可见,但不可响应用户操作,比如来了个电话,前后台切换的过渡状态
// paused:已经暂停了,用户不可见、不可操作,app进入后台
// suspending:应用被挂起,此状态IOS永远不会回调
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
print("didChangeAppLifecycleState: $state");
}
//当前系统改变了一些访问性活动的回调
void didChangeAccessibilityFeatures() {
super.didChangeAccessibilityFeatures();
print("didChangeAccessibilityFeatures");
}
//低内存回调
void didHaveMemoryPressure() {
super.didHaveMemoryPressure();
print("didHaveMemoryPressure");
}
//用户本地设置变化时调用,如系统语言改变
void didChangeLocales(List<Locale>? locale) {
super.didChangeLocales(locale);
print("didChangeLocales");
}
//应用尺寸改变时回调,例如旋转
void didChangeMetrics() {
super.didChangeMetrics();
Size? size = WidgetsBinding.instance?.window.physicalSize;
print("didChangeMetrics :宽:${size?.width} 高:${size?.height}");
}
//系统切换主题时回调
void didChangePlatformBrightness() {
super.didChangePlatformBrightness();
print("didChangePlatformBrightness");
}
///文字系数变化
void didChangeTextScaleFactor() {
super.didChangeTextScaleFactor();
print(
"didChangeTextScaleFactor :${WidgetsBinding.instance?.window.textScaleFactor}");
}
void dispose() {
super.dispose();
WidgetsBinding.instance?.removeObserver(this); //销毁观察者
}
}
- 输出信息
flutter: didChangeMetrics :宽:1125.0 高:2436.0
flutter: didChangeAppLifecycleState: AppLifecycleState.inactive
flutter: didHaveMemoryPressure
flutter: didChangeAppLifecycleState: AppLifecycleState.paused
flutter: didChangePlatformBrightness
flutter: didChangeMetrics :宽:1125.0 高:2436.0
flutter: didChangePlatformBrightness
flutter: didChangeMetrics :宽:1125.0 高:2436.0
flutter: didChangeAppLifecycleState: AppLifecycleState.inactive
flutter: didChangeAppLifecycleState: AppLifecycleState.resumed