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缓存最新数据)。
- 适合复杂异步流处理、事件组合。
适用场景
优缺点
优点 |
缺点 |
功能强大,流操作丰富 |
学习曲线陡峭,易过度设计 |
方便异步复杂逻辑处理 |
代码可读性下降,调试困难 |
代码示例
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
作为主干状态管理框架
- 结合
StateNotifier
或 AsyncNotifier
管理模块化状态逻辑
事件驱动业务
- 使用
BLoC
模型实现高可维护的事件流驱动状态系统
- 常用于支付、审批、认证等流程
异步数据流处理
- 复杂搜索联想、多接口组合等用例推荐使用
RxDart
- 通常配合
Riverpod
或 BLoC
管理 UI 状态