Flutter StatelessWidget、StatefulWidget、InheritedWidget、RenderObjectWidget 等生命周期

102 阅读3分钟

1. StatelessWidget

特点

  • 无状态组件。
  • 适用于不会随时间或用户交互改变的 UI。

生命周期

  1. 构造函数:用于初始化。
  2. build() :唯一的方法,构建组件的 UI。

代码示例

class MyStatelessWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text('I am Stateless');
  }
}

2. StatefulWidget

特点

  • 有状态组件。
  • 适用于需要动态改变状态的组件。

生命周期

方法描述
构造函数创建组件实例,通常用于初始化不可变参数。
createState()创建 State 对象,组件的状态逻辑由此对象管理。
initState()State 对象创建时调用,通常用于初始化数据、监听器等。
didChangeDependencies()在依赖的 InheritedWidget 发生变化时触发,首次创建时也会调用。
build()必须实现的方法,构建组件的 UI。
setState()用于更新组件的状态并重新触发 build()
didUpdateWidget()当父组件重新构建,且传入的参数发生变化时触发。
deactivate()State 被从组件树中临时移除时调用。
dispose()在组件销毁时调用,用于清理资源。

代码示例

class MyStatefulWidget extends StatefulWidget {
  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  @override
  void initState() {
    super.initState();
    print('Init State');
  }

  @override
  Widget build(BuildContext context) {
    return Text('I am Stateful');
  }

  @override
  void dispose() {
    print('Dispose');
    super.dispose();
  }
}

StatelessWidgetStatefulWidget 总结对比

生命周期方法StatelessWidgetStatefulWidget
createState()不适用调用一次
initState()不适用调用一次
didChangeDependencies()不适用可选, 当依赖变化时调用
build()每次构建时调用每次调用 setState() 时都会调用
didUpdateWidget()不适用当父组件传递新的配置时调用
setState()不适用用于更新状态并触发 build()
deactivate()不适用State 从树中移除时调用
dispose()不适用State 永久从树中移除时调用

3. InheritedWidget

特点

  • 用于在组件树中共享数据。
  • 数据更新时,依赖此数据的子组件会重建。

生命周期

  1. 构造函数:创建共享数据。
  2. updateShouldNotify() :判断数据更新时,是否需要通知子组件。

代码示例

class MyInheritedWidget extends InheritedWidget {
  final int count;

  MyInheritedWidget({required this.count, required Widget child}) : super(child: child);

  @override
  bool updateShouldNotify(MyInheritedWidget oldWidget) {
    return oldWidget.count != count;
  }

  static MyInheritedWidget? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
  }
}

4. RenderObjectWidget

特点

  • 低级组件,用于自定义绘制和布局。
  • 通常与 RenderBox 搭配使用。

生命周期

  1. createRenderObject() :创建 RenderObject 实例。
  2. updateRenderObject() :更新 RenderObject 的状态。
  3. didUnmountRenderObject() :在组件从树中移除时调用。

代码示例

class MyRenderObjectWidget extends SingleChildRenderObjectWidget {
  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderBox(); // 自定义 RenderBox
  }

  @override
  void updateRenderObject(BuildContext context, RenderObject renderObject) {
    // 更新 RenderBox 状态
  }
}

5. WidgetAppMaterialApp, CupertinoApp 等)

特点

  • 用于管理应用的根组件。
  • 包含应用的主题、导航和本地化信息。

生命周期

  1. 构造函数:初始化根组件。
  2. build() :构建根组件的 UI。

对比总结

特性StatelessWidgetStatefulWidgetInheritedWidgetRenderObjectWidgetWidgetApp
是否有状态依赖子组件状态自定义状态
复杂性简单中等中等中等
生命周期方法数量少(1个)多(8+个)少(2个)中(3个)少(1个)
适用场景静态 UI动态 UI数据共享自定义布局和绘制管理应用的全局配置和导航
常见用途文本、按钮表单、计数器状态管理高度定制化的 UI应用导航、主题

选择指南

  1. 使用 StatelessWidget:当组件是静态的,不会改变状态。
  2. 使用 StatefulWidget:当需要管理组件内部的状态,比如表单输入、计数器等。
  3. 使用 InheritedWidget:当需要在组件树中共享数据,比如主题、全局状态。
  4. 使用 RenderObjectWidget:当需要完全控制组件的绘制和布局。
  5. 使用 WidgetApp:当需要配置应用的全局设置,比如导航、主题等。