Flutter 生命周期完全指南:从出生到死亡的全过程
什么是生命周期?
在 Flutter 中,生命周期(Lifecycle) 就像人的一生:出生 → 成长 → 衰老 → 死亡。
每个组件从创建到销毁都会经历一系列的阶段,在不同阶段会自动调用特定的方法。理解生命周期可以帮你:
- 在正确的时机做正确的事
- 避免内存泄漏
- 优化应用性能
- 处理数据加载和清理
Flutter 中的生命周期类型
Flutter 有三种主要的生命周期:
- StatelessWidget 生命周期 - 最简单
- StatefulWidget 生命周期 - 最常用
- App 生命周期 - 应用级别
一、StatelessWidget 生命周期
无状态组件的生命周期非常简单,只有一个阶段。
生命周期图
创建 → build() → 显示
代码示例
dart
class MyStatelessWidget extends StatelessWidget {
MyStatelessWidget() {
print('1. 构造函数被调用');
}
@override
Widget build(BuildContext context) {
print('2. build 方法被调用');
return Text('无状态组件');
}
}
执行顺序:
- 构造函数 - 创建组件实例
- build() - 构建界面
特点:
- 只执行一次
- 没有状态管理
- 性能最好
二、StatefulWidget 生命周期(重点)
有状态组件的生命周期最复杂,也是最重要的。
完整生命周期图
创建阶段:
createState() → initState() → didChangeDependencies() → build()
↓
更新阶段: 显示
didUpdateWidget() → build() ←─────────────────────────────┘
↓ ↑
setState() ──────────────────────────────────────────┘
销毁阶段:
deactivate() → dispose()
详细生命周期方法
1. createState()
调用时机: StatefulWidget 被创建时
调用次数: 1次
作用: 创建 State 对象
dart
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() {
print('1. createState - 创建 State 对象');
return _MyWidgetState();
}
}
2. initState()
调用时机: State 对象被插入到树中时
调用次数: 1次
作用: 初始化数据、订阅事件、启动动画等
dart
class _MyWidgetState extends State<MyWidget> {
@override
void initState() {
super.initState(); // 必须先调用
print('2. initState - 初始化');
// 在这里做初始化工作
// ✅ 初始化变量
// ✅ 订阅事件
// ✅ 启动定时器
// ✅ 加载数据
}
}
注意事项:
- 必须调用
super.initState() - 不能使用
BuildContext(还没准备好) - 只执行一次,适合做一次性初始化
3. didChangeDependencies()
调用时机:
- initState() 之后立即调用
- 依赖的 InheritedWidget 改变时
调用次数: 至少1次,可能多次
作用: 处理依赖变化
dart
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('3. didChangeDependencies - 依赖改变');
// 可以使用 context 了
final theme = Theme.of(context);
final mediaQuery = MediaQuery.of(context);
}
4. build()
调用时机:
- didChangeDependencies() 之后
- setState() 之后
- didUpdateWidget() 之后
调用次数: 多次
作用: 构建界面
dart
@override
Widget build(BuildContext context) {
print('4. build - 构建界面');
return Container(
child: Text('Hello'),
);
}
注意事项:
- 会被多次调用,不要在这里做耗时操作
- 应该是纯函数,不要有副作用
- 不要在这里调用 setState()
5. didUpdateWidget()
调用时机: 父组件重建并传入新的配置时
调用次数: 0次或多次
作用: 对比新旧配置,决定是否需要更新
dart
@override
void didUpdateWidget(MyWidget oldWidget) {
super.didUpdateWidget(oldWidget);
print('5. didUpdateWidget - 组件更新');
// 对比新旧配置
if (widget.title != oldWidget.title) {
// 配置改变了,做相应处理
print('标题改变了');
}
}
6. setState()
调用时机: 手动调用
调用次数: 根据需要
作用: 通知 Flutter 重新构建界面
dart
void _updateData() {
setState(() {
print('6. setState - 状态改变');
// 修改状态
count++;
});
// setState 之后会触发 build()
}
7. deactivate()
调用时机: State 对象从树中被移除时
调用次数: 至少1次
作用: 暂时移除时的处理
dart
@override
void deactivate() {
print('7. deactivate - 组件被移除');
super.deactivate();
// 组件可能会被重新插入到树的其他位置
}
8. dispose()
调用时机: State 对象永久移除时
调用次数: 1次
作用: 清理资源、取消订阅、释放内存
dart
@override
void dispose() {
print('8. dispose - 组件销毁');
// 在这里做清理工作
// ✅ 取消定时器
// ✅ 取消网络请求
// ✅ 释放控制器
// ✅ 取消事件订阅
_controller.dispose();
_timer?.cancel();
super.dispose(); // 必须最后调用
}
完整示例:生命周期演示
dart
import 'package:flutter/material.dart';
class LifecycleDemo extends StatefulWidget {
final String title;
LifecycleDemo({required this.title}) {
print('📦 StatefulWidget 构造函数');
}
@override
_LifecycleDemoState createState() {
print('🏗️ 1. createState');
return _LifecycleDemoState();
}
}
class _LifecycleDemoState extends State<LifecycleDemo> {
int _counter = 0;
_LifecycleDemoState() {
print('📦 State 构造函数');
}
@override
void initState() {
super.initState();
print('🎬 2. initState - 初始化');
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
print('🔗 3. didChangeDependencies - 依赖改变');
}
@override
Widget build(BuildContext context) {
print('🎨 4. build - 构建界面 (counter: $_counter)');
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('点击次数:', style: TextStyle(fontSize: 20)),
Text('$_counter', style: TextStyle(fontSize: 50)),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
print('👆 用户点击按钮');
setState(() {
print('🔄 setState - 状态改变');
_counter++;
});
},
child: Text('点击 +1'),
),
],
),
),
);
}
@override
void didUpdateWidget(LifecycleDemo oldWidget) {
super.didUpdateWidget(oldWidget);
print('🔄 5. didUpdateWidget - 组件更新');
if (widget.title != oldWidget.title) {
print(' 标题从 "${oldWidget.title}" 改为 "${widget.title}"');
}
}
@override
void deactivate() {
print('⏸️ 7. deactivate - 组件被移除');
super.deactivate();
}
@override
void dispose() {
print('💀 8. dispose - 组件销毁');
super.dispose();
}
}
// 测试页面
class TestPage extends StatefulWidget {
@override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
bool _showWidget = true;
String _title = '生命周期演示';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('生命周期测试')),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
setState(() {
_showWidget = !_showWidget;
});
},
child: Text(_showWidget ? '隐藏组件' : '显示组件'),
),
SizedBox(width: 10),
ElevatedButton(
onPressed: () {
setState(() {
_title = '新标题 ${DateTime.now().second}';
});
},
child: Text('改变标题'),
),
],
),
Expanded(
child: _showWidget
? LifecycleDemo(title: _title)
: Center(child: Text('组件已隐藏')),
),
],
),
);
}
}
执行顺序示例
首次创建:
📦 StatefulWidget 构造函数
🏗️ 1. createState
📦 State 构造函数
🎬 2. initState
🔗 3. didChangeDependencies
🎨 4. build
点击按钮(setState):
👆 用户点击按钮
🔄 setState
🎨 4. build
父组件更新(改变 title):
📦 StatefulWidget 构造函数
🔄 5. didUpdateWidget
🎨 4. build
组件销毁:
⏸️ 7. deactivate
💀 8. dispose
三、App 生命周期
App 生命周期监听整个应用的状态变化。
App 状态
| 状态 | 说明 |
|---|---|
resumed |
应用可见且响应用户输入(前台运行) |
inactive |
应用可见但不响应用户输入(过渡状态) |
paused |
应用不可见(后台运行) |
detached |
应用即将被系统终止 |
监听 App 生命周期
dart
import 'package:flutter/material.dart';
class AppLifecycleDemo extends StatefulWidget {
@override
_AppLifecycleDemoState createState() => _AppLifecycleDemoState();
}
class _AppLifecycleDemoState extends State<AppLifecycleDemo>
with WidgetsBindingObserver {
@override
void initState() {
super.initState();
// 注册监听器
WidgetsBinding.instance.addObserver(this);
print('📱 注册 App 生命周期监听');
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
print('📱 App 状态改变: $state');
switch (state) {
case AppLifecycleState.resumed:
print(' ✅ 应用进入前台');
// 恢复动画、刷新数据等
break;
case AppLifecycleState.inactive:
print(' ⏸️ 应用处于非活动状态');
break;
case AppLifecycleState.paused:
print(' ⏸️ 应用进入后台');
// 暂停动画、保存数据等
break;
case AppLifecycleState.detached:
print(' 💀 应用即将终止');
break;
}
}
@override
void dispose() {
// 移除监听器
WidgetsBinding.instance.removeObserver(this);
print('📱 移除 App 生命周期监听');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('App 生命周期')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('按 Home 键切换到后台'),
Text('再切回来观察控制台输出'),
],
),
),
);
}
}
App 生命周期实战
dart
class MusicPlayerPage extends StatefulWidget {
@override
_MusicPlayerPageState createState() => _MusicPlayerPageState();
}
class _MusicPlayerPageState extends State<MusicPlayerPage>
with WidgetsBindingObserver {
bool _isPlaying = false;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.paused) {
// 应用进入后台,暂停音乐
if (_isPlaying) {
_pauseMusic();
print('🎵 应用进入后台,自动暂停音乐');
}
} else if (state == AppLifecycleState.resumed) {
// 应用回到前台
print('🎵 应用回到前台');
}
}
void _pauseMusic() {
setState(() {
_isPlaying = false;
});
// 实际的暂停逻辑
}
void _playMusic() {
setState(() {
_isPlaying = true;
});
// 实际的播放逻辑
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('音乐播放器')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
_isPlaying ? Icons.music_note : Icons.music_off,
size: 100,
color: _isPlaying ? Colors.blue : Colors.grey,
),
SizedBox(height: 20),
Text(
_isPlaying ? '正在播放' : '已暂停',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _isPlaying ? _pauseMusic : _playMusic,
child: Text(_isPlaying ? '暂停' : '播放'),
),
SizedBox(height: 20),
Text(
'切换到后台试试',
style: TextStyle(color: Colors.grey),
),
],
),
),
);
}
}
实战案例
案例1:数据加载
dart
class DataLoadingPage extends StatefulWidget {
@override
_DataLoadingPageState createState() => _DataLoadingPageState();
}
class _DataLoadingPageState extends State<DataLoadingPage> {
List<String> _data = [];
bool _isLoading = true;
@override
void initState() {
super.initState();
print('开始加载数据');
_loadData();
}
Future<void> _loadData() async {
// 模拟网络请求
await Future.delayed(Duration(seconds: 2));
if (mounted) { // 检查组件是否还在树中
setState(() {
_data = ['数据1', '数据2', '数据3'];
_isLoading = false;
});
print('数据加载完成');
}
}
@override
void dispose() {
print('页面销毁,取消网络请求');
// 实际项目中应该取消网络请求
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('数据加载')),
body: _isLoading
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: _data.length,
itemBuilder: (context, index) {
return ListTile(title: Text(_data[index]));
},
),
);
}
}
案例2:定时器管理
dart
import 'dart:async';
class TimerPage extends StatefulWidget {
@override
_TimerPageState createState() => _TimerPageState();
}
class _TimerPageState extends State<TimerPage> {
Timer? _timer;
int _seconds = 0;
@override
void initState() {
super.initState();
print('启动定时器');
_startTimer();
}
void _startTimer() {
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
_seconds++;
});
});
}
@override
void dispose() {
print('停止定时器');
_timer?.cancel(); // 必须取消定时器,否则内存泄漏
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('定时器')),
body: Center(
child: Text(
'已运行: $_seconds 秒',
style: TextStyle(fontSize: 30),
),
),
);
}
}
案例3:TextEditingController 管理
dart
class FormPage extends StatefulWidget {
@override
_FormPageState createState() => _FormPageState();
}
class _FormPageState extends State<FormPage> {
late TextEditingController _controller;
@override
void initState() {
super.initState();
print('创建 TextEditingController');
_controller = TextEditingController();
// 监听输入变化
_controller.addListener(() {
print('输入内容: ${_controller.text}');
});
}
@override
void dispose() {
print('释放 TextEditingController');
_controller.dispose(); // 必须释放,否则内存泄漏
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('表单')),
body: Padding(
padding: EdgeInsets.all(20),
child: TextField(
controller: _controller,
decoration: InputDecoration(
labelText: '输入内容',
border: OutlineInputBorder(),
),
),
),
);
}
}
案例4:动画控制器
dart
class AnimationPage extends StatefulWidget {
@override
_AnimationPageState createState() => _AnimationPageState();
}
class _AnimationPageState extends State<AnimationPage>
with SingleTickerProviderStateMixin {
late AnimationController _animationController;
late Animation<double> _animation;
@override
void initState() {
super.initState();
print('创建动画控制器');
_animationController = AnimationController(
duration: Duration(seconds: 2),
vsync: this,
);
_animation = Tween<double>(begin: 0, end: 300).animate(
_animationController,
);
_animationController.repeat(reverse: true);
}
@override
void dispose() {
print('释放动画控制器');
_animationController.dispose(); // 必须释放
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('动画')),
body: Center(
child: AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Container(
width: _animation.value,
height: _animation.value,
color: Colors.blue,
);
},
),
),
);
}
}
常见问题
1. initState 中可以使用 context 吗?
不推荐直接使用,因为此时 context 还没完全准备好。
dart
@override
void initState() {
super.initState();
// ❌ 错误:可能会出问题
// showDialog(context: context, ...);
// ✅ 正确:延迟到下一帧
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(context: context, builder: (context) => AlertDialog());
});
}
2. 为什么要检查 mounted?
防止在组件销毁后调用 setState()。
dart
Future<void> _loadData() async {
await Future.delayed(Duration(seconds: 2));
// ✅ 检查组件是否还在树中
if (mounted) {
setState(() {
// 更新状态
});
}
}
3. dispose 中应该做什么?
必须清理的资源:
- ✅ Timer -
_timer?.cancel() - ✅ AnimationController -
_controller.dispose() - ✅ TextEditingController -
_controller.dispose() - ✅ ScrollController -
_controller.dispose() - ✅ StreamSubscription -
_subscription?.cancel() - ✅ 事件监听 - 移除监听器
4. setState 可以在哪里调用?
可以调用的地方:
- ✅ 事件回调中(按钮点击等)
- ✅ Future/async 回调中(检查 mounted)
- ✅ Timer 回调中
- ✅ Stream 监听中
不能调用的地方:
- ❌ build() 方法中
- ❌ initState() 中(还没 build)
- ❌ dispose() 中(已经销毁)
生命周期最佳实践
1. 资源管理原则
dart
// ✅ 好的实践
class GoodWidget extends StatefulWidget {
@override
_GoodWidgetState createState() => _GoodWidgetState();
}
class _GoodWidgetState extends State<GoodWidget> {
Timer? _timer;
TextEditingController? _controller;
@override
void initState() {
super.initState();
// 创建资源
_timer = Timer.periodic(Duration(seconds: 1), (_) {});
_controller = TextEditingController();
}
@override
void dispose() {
// 释放资源
_timer?.cancel();
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
2. 异步操作处理
dart
class AsyncWidget extends StatefulWidget {
@override
_AsyncWidgetState createState() => _AsyncWidgetState();
}
class _AsyncWidgetState extends State<AsyncWidget> {
bool _isLoading = false;
@override
void initState() {
super.initState();
_loadData();
}
Future<void> _loadData() async {
if (!mounted) return;
setState(() => _isLoading = true);
try {
await Future.delayed(Duration(seconds: 2));
// ✅ 检查 mounted
if (mounted) {
setState(() => _isLoading = false);
}
} catch (e) {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
@override
Widget build(BuildContext context) {
return _isLoading
? CircularProgressIndicator()
: Text('加载完成');
}
}
3. 避免内存泄漏
dart
class NoLeakWidget extends StatefulWidget {
@override
_NoLeakWidgetState createState() => _NoLeakWidgetState();
}
class _NoLeakWidgetState extends State<NoLeakWidget>
with WidgetsBindingObserver {
Timer? _timer;
StreamSubscription? _subscription;
@override
void initState() {
super.initState();
// 注册监听
WidgetsBinding.instance.addObserver(this);
// 创建定时器
_timer = Timer.periodic(Duration(seconds: 1), (_) {});
// 订阅 Stream
_subscription = Stream.periodic(Duration(seconds: 1)).listen((_) {});
}
@override
void dispose() {
// ✅ 清理所有资源
WidgetsBinding.instance.removeObserver(this);
_timer?.cancel();
_subscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
生命周期速查表
StatefulWidget 生命周期
| 方法 | 调用时机 | 次数 | 用途 |
|---|---|---|---|
createState() |
创建时 | 1次 | 创建 State |
initState() |
插入树时 | 1次 | 初始化 |
didChangeDependencies() |
依赖改变 | ≥1次 | 处理依赖 |
build() |
构建界面 | 多次 | 返回 Widget |
didUpdateWidget() |
配置更新 | ≥0次 | 对比配置 |
setState() |
手动调用 | 按需 | 触发重建 |
deactivate() |
移除时 | ≥1次 | 暂时移除 |
dispose() |
销毁时 | 1次 | 清理资源 |
App 生命周期
| 状态 | 说明 | 应该做什么 |
|---|---|---|
resumed |
前台运行 | 恢复动画、刷新数据 |
inactive |
非活动 | 暂停部分操作 |
paused |
后台运行 | 暂停动画、保存数据 |
detached |
即将终止 | 最后的清理 |
总结
生命周期的核心原则:
- 创建时初始化 - 在 initState() 中创建资源
- 销毁时清理 - 在 dispose() 中释放资源
- 检查 mounted - 异步操作前检查组件是否还在
- 避免泄漏 - 所有创建的资源都要释放
记住这个公式:
创建资源 (initState) + 使用资源 (build) + 释放资源 (dispose) = 完美生命周期
最重要的三个方法:
initState()- 初始化一切build()- 构建界面dispose()- 清理一切
理解并正确使用生命周期,你的 Flutter 应用将更加稳定、高效、无内存泄漏!