Flutter 生命周期完全指南:从出生到死亡的全过程

Flutter 生命周期完全指南:从出生到死亡的全过程

什么是生命周期?

在 Flutter 中,生命周期(Lifecycle) 就像人的一生:出生 → 成长 → 衰老 → 死亡。

每个组件从创建到销毁都会经历一系列的阶段,在不同阶段会自动调用特定的方法。理解生命周期可以帮你:

  • 在正确的时机做正确的事
  • 避免内存泄漏
  • 优化应用性能
  • 处理数据加载和清理

Flutter 中的生命周期类型

Flutter 有三种主要的生命周期:

  1. StatelessWidget 生命周期 - 最简单
  2. StatefulWidget 生命周期 - 最常用
  3. App 生命周期 - 应用级别

一、StatelessWidget 生命周期

无状态组件的生命周期非常简单,只有一个阶段。

生命周期图

复制代码
创建 → build() → 显示

代码示例

dart 复制代码
class MyStatelessWidget extends StatelessWidget {
  MyStatelessWidget() {
    print('1. 构造函数被调用');
  }

  @override
  Widget build(BuildContext context) {
    print('2. build 方法被调用');
    return Text('无状态组件');
  }
}

执行顺序:

  1. 构造函数 - 创建组件实例
  2. 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 即将终止 最后的清理

总结

生命周期的核心原则:

  1. 创建时初始化 - 在 initState() 中创建资源
  2. 销毁时清理 - 在 dispose() 中释放资源
  3. 检查 mounted - 异步操作前检查组件是否还在
  4. 避免泄漏 - 所有创建的资源都要释放

记住这个公式:

复制代码
创建资源 (initState) + 使用资源 (build) + 释放资源 (dispose) = 完美生命周期

最重要的三个方法:

  • initState() - 初始化一切
  • build() - 构建界面
  • dispose() - 清理一切

理解并正确使用生命周期,你的 Flutter 应用将更加稳定、高效、无内存泄漏!

相关推荐
2501_948122632 小时前
React Native for OpenHarmony 实战:Steam 资讯 App 帮助中心实现
javascript·react native·react.js·游戏·ecmascript·harmonyos
YAY_tyy2 小时前
Turfjs 性能优化:大数据量地理要素处理技巧
前端·3d·arcgis·cesium·turfjs
hhcccchh2 小时前
学习vue第十二天 Vue开发工具链指南:从手工作坊到现代化工厂
前端·vue.js·学习
Yeats_Liao2 小时前
模型选型指南:7B、67B与MoE架构的业务适用性对比
前端·人工智能·神经网络·机器学习·架构·deep learning
念念不忘 必有回响2 小时前
Vue页面布局与路由映射实战:RouterView嵌套及动态组件生成详解
前端·javascript·vue.js
HH思️️无邪2 小时前
Flutter 项目 -从 0 到 1 实现 iOS WatchApp
flutter·ios
冰暮流星2 小时前
javascript数据类型转换-转换为数字型
开发语言·前端·javascript
—Qeyser2 小时前
Flutter StatelessWidget 完全指南:构建高效的静态界面
前端·flutter
小雨下雨的雨2 小时前
Flutter鸿蒙共赢——像素的解构:沃罗诺伊点描与权重平衡的艺术
flutter·ui·华为·harmonyos·鸿蒙系统