Flutter状态管理全解析

setState

底层原理
  • StatefulWidget挂载对应State对象,保存局部状态。
  • 调用setState()时,标记该State为“dirty”,等待下一帧异步触发build()。
  • Flutter框架通过Element树遍历标记为dirty的节点,重建UI,优化性能。
适用场景
  • 简单、局部状态,UI与逻辑耦合。
  • 不跨组件传递状态。
优缺点
优点 缺点
原生支持,无依赖 只适合局部状态,难以跨组件共享
简单明了 业务逻辑和UI耦合,难测试
性能优秀(局部重建) 状态管理复杂时难维护
代码示例
class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _count = 0;

  void _increment() {
    setState(() {
      _count++; // 状态改变,标记重建UI
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $_count'),
        ElevatedButton(onPressed: _increment, child: Text('Increment')),
      ],
    );
  }
}

Provider

底层原理
  • 依托Flutter内置的InheritedWidget,通过Widget树向下传递数据。
  • 状态类一般继承ChangeNotifier,通过notifyListeners()通知监听者。
  • UI通过Consumer或context.watch()获取状态,监听变化重建对应Widget。
适用场景
  • 中小型项目跨组件状态共享。
  • 简单业务逻辑,无需复杂事件处理。
优缺点
优点 缺点
简洁,社区广泛支持 依赖BuildContext,跨模块受限
支持细粒度监听(Selector) 异步状态管理不够优雅
性能优良(避免无谓重建) 复杂业务逻辑不够灵活
代码示例
mport 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class MainAPP extends StatelessWidget {
  const MainAPP({super.key});
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "flutter dome",
      color: Colors.grey,
      theme: ThemeData(),
      home: Scaffold(
          body: ChangeNotifierProvider(
              create: (_) => CounterModel(),
              child: CounterView(),
          ))
    );
  }
}


class CounterModel extends ChangeNotifier {
  int count = 0;
  void increment() {
    count++;
    notifyListeners(); // 通知所有监听者更新 UI
  }
}
class CounterView extends StatelessWidget {
  const CounterView({super.key});

  @override
  Widget build(BuildContext context) {
    final model = Provider.of<CounterModel>(context);
    return Column(
      children: [
        // 组件1
        Text('Count: ${model.count}'),
        ElevatedButton(
          onPressed: model.increment,
          child: Text('Increment'),
        ),
        //子组件共享状态
        // 组件2
        CounterSubView()
      ],
    );
  }
}

class CounterSubView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 1.写法
    // final model = Provider.of<CounterModel>(context);

    // 2.写法
    // final model = context.watch<CounterModel>();
    // final model = context.read<CounterModel>()
    // return Text('${model.count}');

    // 3.写法
    return Consumer<CounterModel>(builder: (context, counter, _) =>Text('${counter.count}')   );
  }
}

Riverpod

底层原理
  • 独立于BuildContext的状态管理,通过ProviderContainer集中管理状态。
  • 通过声明式Provider定义状态,自动追踪依赖,状态变更自动通知订阅者。
  • 支持多种Provider类型(StateProvider, FutureProvider, StreamProvider, StateNotifierProvider等)。
    *支持懒加载、自动Dispose,避免内存泄露。
适用场景
  • 中大型项目,复杂模块状态。
  • 需要灵活组合、测试友好。
优缺点
优点 缺点
无需BuildContext,支持全局访问 学习曲线较陡
支持异步状态,丰富Provider类型 生态较新,社区资源相对较少
自动Dispose管理生命周期,防止泄露 代码结构需规范
代码示例

class MainAPP extends StatelessWidget {
  const MainAPP({super.key});
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
  // 根目录 ProviderScope
    return ProviderScope(
      child: MaterialApp(
        title: "flutter dome",
        color: Colors.grey,
        theme: ThemeData(),
        home: Scaffold(body: RiverpodExample()),
      ),
    );
  }
}
  // 全局不依赖 context
final counterProvider = StateProvider<int>((ref) => 0);

class RiverpodExample extends ConsumerWidget {
  const RiverpodExample({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);

    return Scaffold(
      appBar: AppBar(title: Text('Riverpod Example')),
      body: Center(child: Text('Count: $count')),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).state++,
        child: Icon(Icons.add),
      ),
    );
  }
}

Bloc

底层原理
  • 通过Stream和Sink管理事件输入和状态输出。
  • UI层发出事件(如按钮点击),通过Sink传入BLoC。
  • BLoC内处理事件,输出新的状态流(Stream)。
  • UI通过StreamBuilder订阅状态流,自动刷新界面。
  • 明确区分事件与状态,符合单向数据流。
适用场景
  • 业务复杂,流程清晰。
  • 代码可测试、可复用。
  • 大型项目。
优缺点
优点 缺点
无需BuildContext,支持全局访问 学习曲线较陡
支持异步状态,丰富Provider类型 生态较新,社区资源相对较少
自动Dispose管理生命周期,防止泄露 代码结构需规范
import 'dart:async';
import 'package:flutter/material.dart';

// 事件定义
abstract class CounterEvent {}
class IncrementEvent extends CounterEvent {}

// 状态定义
class CounterState {
  final int count;
  CounterState(this.count);
}

class CounterBloc {
  int _count = 0;

  // 事件控制器
  final _eventController = StreamController<CounterEvent>();
  Sink<CounterEvent> get eventSink => _eventController.sink;

  // 状态控制器
  final _stateController = StreamController<CounterState>();
  Stream<CounterState> get stateStream => _stateController.stream;

  CounterBloc() {
    _eventController.stream.listen(_mapEventToState);
  }

  void _mapEventToState(CounterEvent event) {
    if (event is IncrementEvent) {
      _count++;
      _stateController.sink.add(CounterState(_count));
    }
  }

  void dispose() {
    _eventController.close();
    _stateController.close();
  }
}

class BlocExample extends StatefulWidget {
  @override
  _BlocExampleState createState() => _BlocExampleState();
}

class _BlocExampleState extends State<BlocExample> {
  final CounterBloc bloc = CounterBloc();

  @override
  void dispose() {
    bloc.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('BLoC Example')),
      body: StreamBuilder<CounterState>(
        stream: bloc.stateStream,
        initialData: CounterState(0),
        builder: (context, snapshot) {
          return Center(child: Text('Count: ${snapshot.data!.count}'));
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => bloc.eventSink.add(IncrementEvent()),
        child: Icon(Icons.add),
      ),
    );
  }
}

GetX

底层原理

  • 通过 .obs包装变量,变成响应式对象。
  • 使用 Obx Widget监听响应式变量, 变量变化时自动刷新。
  • 提供依赖注入和路由管理,集成度高。
    适用场景
  • 快速开发,简单项目。
  • 需要轻量、零模板代码。
优缺点
优点 缺点
极简语法,易上手 依赖全局状态,代码难维护
集成路由、依赖注入 大型项目不推荐,测试困难
零模板,响应式更新 状态管理粒度不细

代码示例

// 首页
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: "GetX 综合示例",
      debugShowCheckedModeBanner: false,
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      home: HomePage(),
      getPages: [
        GetPage(name: '/', page: () => HomePage()),
        GetPage(name: '/detail', page: () => DetailPage()),
      ],
    );
  }
}

class HomePage extends StatelessWidget {
  HomePage({super.key}){
    // 在这里注册控制器(只执行一次)
    Get.lazyPut<DemoController>(() => DemoController(), fenix: true);
  }
  // 直接实例化
  final ScoreController scoreController = Get.put(ScoreController());

  @override
  Widget build(BuildContext context) {
    // 用 Get.find 获取懒加载的控制器
    // 这里拿到实例
    final demoCtrl = Get.find<DemoController>();
    return Scaffold(
      appBar: AppBar(title: Text("GetX 综合示例")),
      body: SingleChildScrollView(
        child: Column(
          children: [
            // 响应式UI - Obx
            Obx(() => Text("计数器: ${demoCtrl.count}", style: TextStyle(fontSize: 24))),
            ElevatedButton(
              onPressed: demoCtrl.increment,
              child: Text("计数器 +1"),
            ),
            SizedBox(height: 20),

            // 手动刷新 UI - GetBuilder
            GetBuilder<ScoreController>(
              builder: (c) => Text("手动刷新分数: ${c.score}", style: TextStyle(fontSize: 24)),
            ),
            ElevatedButton(
              onPressed: scoreController.increase,
              child: Text("分数 +1"),
            ),
            SizedBox(height: 20),

            // 修改 user 响应式对象
            Obx(() => Text("用户名字: ${demoCtrl.user.value.name}, 年龄: ${demoCtrl.user.value.age}")),
            ElevatedButton(
              onPressed: () => demoCtrl.changeUserName("李四"),
              child: Text("修改用户名"),
            ),
            SizedBox(height: 20),

            // 列表响应式
            Obx(() => Text("项目数量: ${demoCtrl.items.length}")),
            ElevatedButton(
              onPressed: () => demoCtrl.addItem("项目 ${demoCtrl.items.length + 1}"),
              child: Text("添加项目"),
            ),
            SizedBox(height: 20),

            // 弹窗示例
            ElevatedButton(
              onPressed: () => Get.defaultDialog(
                title: "提示",
                middleText: "这是一个默认弹窗",
                onConfirm: () => Get.back(),
                textConfirm: "确认",
              ),
              child: Text("显示弹窗"),
            ),
            SizedBox(height: 20),

            // Snackbar示例
            ElevatedButton(
              onPressed: () => Get.snackbar("标题", "这是一个Snackbar通知",
                  snackPosition: SnackPosition.BOTTOM),
              child: Text("显示Snackbar"),
            ),
            SizedBox(height: 20),

            // BottomSheet示例
            ElevatedButton(
              onPressed: () => Get.bottomSheet(Container(
                color: Colors.white,
                child: Wrap(
                  children: [
                    ListTile(
                      leading: Icon(Icons.light_mode),
                      title: Text("浅色主题"),
                      onTap: () => Get.changeTheme(ThemeData.light()),
                    ),
                    ListTile(
                      leading: Icon(Icons.dark_mode),
                      title: Text("深色主题"),
                      onTap: () => Get.changeTheme(ThemeData.dark()),
                    ),
                  ],
                ),
              )),
              child: Text("显示底部弹窗并切换主题"),
            ),
            SizedBox(height: 20),

            // 路由跳转带参数
            ElevatedButton(
              onPressed: () {
                Get.toNamed('/detail', arguments: {"id": 123, "message": "你好 from 首页"});
              },
              child: Text("跳转到详情页带参数"),
            ),
            SizedBox(height: 20),

            // 控制器生命周期演示按钮
            ElevatedButton(
              onPressed: () {
                final ctrl = Get.put(LifecycleController());
                ctrl.showSnackbar();
              },
              child: Text("测试控制器生命周期"),
            ),
          ],
        ),
      ),
    );
  }
}

// 详情页,接收参数,返回数据示例
class DetailPage extends StatelessWidget {
  const DetailPage({super.key});

  @override
  Widget build(BuildContext context) {
    // 获取参数
    final args = Get.arguments ?? {};
    final id = args['id'] ?? 0;
    final message = args['message'] ?? '';

    return Scaffold(
      appBar: AppBar(title: Text("详情页")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("收到参数:id = $id", style: TextStyle(fontSize: 22)),
            Text("消息: $message", style: TextStyle(fontSize: 18)),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Get.back(result: "详情页返回的数据");
              },
              child: Text("返回并携带数据"),
            )
          ],
        ),
      ),
    );
  }
}

// 控制器生命周期示例
class LifecycleController extends GetxController {
  @override
  void onInit() {
    super.onInit();
    print("LifecycleController onInit");
  }

  @override
  void onReady() {
    super.onReady();
    print("LifecycleController onReady");
  }

  @override
  void onClose() {
    print("LifecycleController onClose");
    super.onClose();
  }

  void showSnackbar() {
    Get.snackbar("Lifecycle", "控制器生命周期打印日志, 查看控制台");
  }
}

总结:

原理点 说明
响应式变量(.obs GetX 使用 Rx<T> 类型将普通变量变成响应式数据。底层基于 Dart 的 Stream 概念(不是 Stream 实现),实现高性能数据监听。
自动 UI 更新(Obx) Obx Widget 会注册为 .obs 变量的监听器,当 .obs 的值变化时,Obx 自动触发 build() 刷新自身。
依赖注入 DI 使用 Get.put() / Get.lazyPut() 将控制器或对象注册到全局容器中,可用 Get.find() 取出。是轻量级服务定位器(Service Locator)实现。
导航路由 GetMaterialApp 替代 MaterialApp,集成路由功能(如:Get.to()Get.back()),支持传参、返回、动态路由、嵌套路由等。
状态更新(可选手动) .obs 外,还可以使用 GetBuilder() + update() 手动刷新,适用于不想使用响应式变量的情况。

RxDart

底层原理

  • Dart原生Stream的扩展库,添加丰富操作符(map, filter, debounce等)。
  • 采用Subject概念(如BehaviorSubject缓存最新数据)。
  • 适合复杂异步流处理、事件组合。

适用场景

  • 复杂数据流组合、异步处理。
  • 结合MVVM架构。
优缺点
优点 缺点
功能强大,流操作丰富 学习曲线陡峭,易过度设计
方便异步复杂逻辑处理 代码可读性下降,调试困难
代码示例
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';

class RxDartExample extends StatefulWidget {
  @override
  _RxDartExampleState createState() => _RxDartExampleState();
}

class _RxDartExampleState extends State<RxDartExample> {
  final _countSubject = BehaviorSubject<int>.seeded(0);

  void _increment() {
    _countSubject.add(_countSubject.value + 1);
  }

  @override
  void dispose() {
    _countSubject.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('RxDart Example')),
      body: StreamBuilder<int>(
        stream: _countSubject.stream,
        initialData: _countSubject.value,
        builder: (context, snapshot) {
          return Center(child: Text('Count: ${snapshot.data}'));
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _increment,
        child: Icon(Icons.add),
      ),
    );
  }
}

✅ 总结对比

管理方式 状态作用域 学习成本 性能 解耦性 适合场景 特点说明
setState 单个组件内部 ⭐️ ⭐️⭐️⭐️ 局部更新、临时状态 官方自带、零依赖、简单易用,适合新手和Demo
Provider 整个 Widget 树 ⭐️⭐️ ⭐️⭐️⭐️ ⭐️⭐️ 跨组件状态共享,如用户登录、设置切换 Flutter 推荐方案,轻量、易上手,适合中小型项目
Riverpod 全局作用域 ⭐️⭐️⭐️ ⭐️⭐️⭐️ ⭐️⭐️⭐️ 中大型项目、复杂模块解耦 构建灵活、自动销毁、无 BuildContext
BLoC 全局/模块化 ⭐️⭐️⭐️⭐️ ⭐️⭐️ ⭐️⭐️⭐️⭐️ 流程明确的复杂业务场景,如支付流程 解耦性强、利于单元测试,适合大型团队协作开发
GetX 全局 + 局部响应式 ⭐️ ⭐️⭐️⭐️⭐️ ⭐️ 快速开发工具型 App、小程序型 App 快、极简、功能全,维护性略逊,适合单人/小团队项目
RxDart 自定义流控制与组合 ⭐️⭐️⭐️⭐️ ⭐️⭐️⭐️ ⭐️⭐️⭐️ 异步复杂场景:搜索联想、图表动画 强大灵活,适合对流式编程有经验的开发者

实战选型建议

小型项目 / 快速 MVP

  • 使用 setState + Provider 快速完成 UI 和状态绑定
  • 如为单人项目或临时工具型项目,GetX 开发效率更高

中大型商业项目

  • 使用 Riverpod 作为主干状态管理框架
  • 结合 StateNotifierAsyncNotifier 管理模块化状态逻辑

事件驱动业务

  • 使用 BLoC 模型实现高可维护的事件流驱动状态系统
  • 常用于支付、审批、认证等流程

异步数据流处理

  • 复杂搜索联想、多接口组合等用例推荐使用 RxDart
  • 通常配合 RiverpodBLoC 管理 UI 状态
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容