🔄 状态组件详解

状态管理是 Flutter 开发的核心概念。本页面将详细介绍各种状态组件和状态管理方案。

🎯 StatelessWidget

StatelessWidget 是无状态组件,其 UI 只依赖于传入的参数,不依赖内部状态。

基本用法

class MyTextWidget extends StatelessWidget {
  final String text;
  final Color color;

  const MyTextWidget({
    Key? key,
    required this.text,
    this.color = Colors.black,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: TextStyle(color: color),
    );
  }
}

使用场景

  • 静态内容展示
  • 纯 UI 组件
  • 不涉及状态变化的场景
💡 提示:StatelessWidget 更轻量,性能更好,在不需要状态管理的场景下优先使用。

🔄 StatefulWidget

StatefulWidget 是有状态组件,可以维护内部状态,状态变化时会重新构建 UI。

基本用法

class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State {
  int _counter = 0;

  void _increment() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          '计数器: $_counter',
          style: TextStyle(fontSize: 24),
        ),
        SizedBox(height: 20),
        ElevatedButton(
          onPressed: _increment,
          child: Text('增加'),
        ),
      ],
    );
  }
}

生命周期

  • initState():组件初始化时调用
  • build():构建 UI 时调用
  • didUpdateWidget():父组件重建时调用
  • setState():更新状态并重建 UI
  • dispose():组件销毁时调用
💡 提示:使用 setState() 更新状态时,Flutter 会自动调用 build() 方法重新构建 UI。

📡 InheritedWidget

InheritedWidget 是用于在组件树中向下传递数据的组件,常用于状态管理。

基本用法

class CounterProvider extends InheritedWidget {
  final int counter;
  final VoidCallback increment;

  const CounterProvider({
    Key? key,
    required this.counter,
    required this.increment,
    required Widget child,
  }) : super(key: key, child: child);

  static CounterProvider of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType()!;
  }

  @override
  bool updateShouldNotify(CounterProvider oldWidget) {
    return counter != oldWidget.counter;
  }
}

// 使用示例
class CounterWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final provider = CounterProvider.of(context);
    return Column(
      children: [
        Text('计数器: ${provider.counter}'),
        ElevatedButton(
          onPressed: provider.increment,
          child: Text('增加'),
        ),
      ],
    );
  }
}

使用场景

  • 全局状态管理
  • 主题管理
  • 用户信息传递
💡 提示:InheritedWidget 是许多状态管理方案(如 Provider、Bloc)的基础。

⏳ FutureBuilder

FutureBuilder 用于根据 Future 的状态构建不同的 UI。

基本用法

FutureBuilder(
  future: _fetchData(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator();
    } else if (snapshot.hasError) {
      return Text('错误: ${snapshot.error}');
    } else if (snapshot.hasData) {
      return Text('数据: ${snapshot.data}');
    } else {
      return Text('无数据');
    }
  },
)

Future _fetchData() async {
  await Future.delayed(Duration(seconds: 2));
  return '获取的数据';
}

状态类型

  • none:Future 未开始
  • waiting:正在等待结果
  • active:正在执行
  • done:已完成
💡 提示:FutureBuilder 适用于一次性异步操作,如网络请求、文件读取等。

📡 StreamBuilder

StreamBuilder 用于根据 Stream 的数据流构建 UI,适用于持续的数据更新场景。

基本用法

StreamBuilder(
  stream: _counterStream,
  builder: (context, snapshot) {
    if (snapshot.hasError) {
      return Text('错误: ${snapshot.error}');
    }
    switch (snapshot.connectionState) {
      case ConnectionState.none:
        return Text('等待连接...');
      case ConnectionState.waiting:
        return CircularProgressIndicator();
      case ConnectionState.active:
        return Text('计数: ${snapshot.data}');
      case ConnectionState.done:
        return Text('流已结束');
    }
  },
)

Stream get _counterStream async* {
  for (int i = 0; i < 10; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

使用场景

  • 实时数据更新
  • WebSocket 连接
  • 用户输入监听
  • 数据库查询
💡 提示:StreamBuilder 适用于持续的数据流,如实时聊天、股票价格等场景。