1. StatefulWidget的生命周期方法执行顺序是怎样的?
createState-
initState(只调用一次,初始化数据、监听器等) -
didChangeDependencies(在initState后立即调用,且每次依赖变化时调用) build-
didUpdateWidget(父 Widget 重建导致配置变化时调用) -
deactivate(从树中移除时调用) -
dispose(永久销毁时调用)
⚠️ 注意事项:
- 不要在
initState中调用BuildContext.dependOnInheritedWidgetOfExactType,应在didChangeDependencies中获取。setState不能在dispose后调用。
2. didUpdateWidget 会在什么情况下被调用?
- 当父组件重建且传递给当前
StatefulWidget的配置(widget参数)发生变化时触发。 -
注意:如果父组件只是重新
build,但传给子组件的旧对象和新对象相同(同引用),则不会触发。
⚠️ 注意事项:
- 此方法中可根据新旧
widget的差异执行相应操作(例如网络请求刷新数据),但记得调用super.didUpdateWidget。
3. didChangeDependencies 何时触发?
- 在
initState之后立即调用。 - 每当该
State所依赖的InheritedWidget发生变化时(例如Theme、Locale变化),再次调用。 - 也可用于在依赖变化后手动触发重建。
⚠️ 注意事项:
- 通常在此方法中执行那些依赖于
InheritedWidget的初始化操作,如MediaQuery的获取。- 避免在此方法中频繁调用
setState。
4 State 的 reassemble 方法何时调用?
答案: 仅在开发环境中,当执行热重载(Hot Reload)时调用,允许 State 重新初始化资源。生产环境下不会调用。
⚠️ 注意事项: 可用于重置动画控制器或重新加载网络数据,但注意不要依赖它做业务逻辑。
5. didChangeAppLifecycleState 是什么?有哪些状态?
答案: 是 WidgetsBindingObserver 提供的方法,监听应用生命周期变化。状态包括:resumed(可见可交互)、inactive(可见但不可交互)、paused(不可见)、detached(即将销毁)。
⚠️ 注意事项: 需要在 initState 中添加观察者,dispose 中移除。
6. StatefulWidget 调用 setState 后会立即执行 build 吗?
答案: 不会立即执行,而是将当前 State 标记为 dirty,在当前帧的 build 阶段统一调度,下一帧绘制前执行 build。
⚠️ 注意事项: 多次调用 setState 会合并成一个重建,无需担心性能。
7. didUpdateWidget 和 build 的关系?谁先调用?
答案: 当父组件重建导致配置变化时,didUpdateWidget 先调用,然后才会触发 build(如果标记了 dirty)。
⚠️ 注意事项: 在 didUpdateWidget 中可以比较旧 widget 和新 widget 的差异来决定是否修改状态或发起网络请求。
8. deactivate 和 dispose 的区别?
答案: deactivate 表示 State 从树中移除(但可能重新插入到树的其他位置,如通过 GlobalKey 移动)。dispose 表示永久销毁,不会再被使用。
⚠️ 注意事项: 在 dispose 中清理所有资源(监听器、控制器、Stream 等),否则会导致内存泄漏。
9. 在 initState 中可以调用 setState 吗?为什么?
答案: 不应该调用。因为此时 State 尚未完全关联到 BuildContext,调用 setState 会触发延迟构建,但框架会发出警告。正确做法是在 didChangeDependencies 中执行。
⚠️ 注意事项: 可以通过 Future.microtask 或 addPostFrameCallback 在下一帧执行 setState。
10.Route 的生命周期有哪些?
答案: Route 会经历:constructor → install(插入 Navigator) → didPush → didChangeNext/didChangePrevious → didPop → dispose。
⚠️ 注意事项: 自定义 Route 可重写这些方法实现过渡动画或弹出拦截。
11. WidgetsBinding 的 addPostFrameCallback 作用?
答案: 在当前帧绘制完成后执行回调,常用于需要在首次布局后获取尺寸或执行一次后置操作。
⚠️ 注意事项: 该回调只会执行一次,如果需要多次监听,每次都要重新添加。
12 Flutter 应用的启动生命周期顺序是怎样的?
答案:
- main() → runApp()
- WidgetsFlutterBinding.ensureInitialized()
- 创建 WidgetsBinding,初始化平台通道等
- 调度第一帧(scheduleWarmUpFrame)
- 构建根 Widget(runApp 传入的 Widget)
- 执行 initState、build、布局绘制
⚠️ 注意事项: runApp 后应用即开始启动,但第一帧未完成前无法交互。