flutter学习之状态管理相关组件

Flutter 状态管理全面指南

状态管理是 Flutter 开发中的核心概念,理解不同场景下的状态管理方案至关重要。

一、状态管理基础

1. StatefulWidget 基础状态管理

dart 复制代码
class CounterWidget extends StatefulWidget {
@override
_CounterWidgetState createState() => _CounterWidgetState();
}

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

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

@override
Widget build(BuildContext context) {
return Column(
children: [
Text('计数器: $_counter'),
ElevatedButton(
onPressed: _increment,
child: Text('增加'),
),
],
);
}
}

2. 状态提升 (Lifting State Up)

dart 复制代码
// 父组件管理状态
class ParentWidget extends StatefulWidget {
@override
_ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
int _counter = 0;

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

@override
Widget build(BuildContext context) {
return Column(
children: [
// 显示状态
DisplayWidget(counter: _counter),
// 修改状态
ControlWidget(onIncrement: _increment),
],
);
}
}

// 只负责显示的子组件
class DisplayWidget extends StatelessWidget {
final int counter;

DisplayWidget({required this.counter});

@override
Widget build(BuildContext context) {
return Text('计数器: $counter');
}
}

// 只负责控制的子组件
class ControlWidget extends StatelessWidget {
final VoidCallback onIncrement;

ControlWidget({required this.onIncrement});

@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onIncrement,
child: Text('增加'),
);
}
}

二、InheritedWidget 状态共享

1. 基础 InheritedWidget

dart 复制代码
// 1. 创建 InheritedWidget
class CounterInheritedWidget extends InheritedWidget {
final int counter;
final VoidCallback increment;

CounterInheritedWidget({
required this.counter,
required this.increment,
required Widget child,
}) : super(child: child);

// 2. 定义静态方法方便子组件访问
static CounterInheritedWidget? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<CounterInheritedWidget>();
}

// 3. 当数据变化时通知依赖的子组件
@override
bool updateShouldNotify(CounterInheritedWidget oldWidget) {
return counter != oldWidget.counter;
}
}

// 4. 使用 InheritedWidget
class InheritedExample extends StatefulWidget {
@override
_InheritedExampleState createState() => _InheritedExampleState();
}

class _InheritedExampleState extends State<InheritedExample> {
int _counter = 0;

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

@override
Widget build(BuildContext context) {
return CounterInheritedWidget(
counter: _counter,
increment: _increment,
child: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
DisplayWidget(),
SizedBox(height: 20),
ControlWidget(),
],
),
),
),
);
}
}

// 5. 子组件访问共享状态
class DisplayWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = CounterInheritedWidget.of(context)?.counter ?? 0;
return Text('计数器: $counter');
}
}

class ControlWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final increment = CounterInheritedWidget.of(context)?.increment;
return ElevatedButton(
onPressed: increment,
child: Text('增加'),
);
}
}

三、Provider(官方推荐)

1. Provider 基础使用

yaml 复制代码
# pubspec.yaml
dependencies:
provider: ^6.0.0
dart 复制代码
// 1. 创建 Model
class CounterModel with ChangeNotifier {
int _count = 0;

int get count => _count;

void increment() {
_count++;
notifyListeners(); // 通知监听者
}

void decrement() {
_count--;
notifyListeners();
}
}

// 2. 在顶层提供 Model
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CounterModel()),
// 可以添加更多 Provider
],
child: MyApp(),
),
);
}

// 3. 消费数据
class CounterDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 方式1: 使用 Consumer
return Consumer<CounterModel>(
builder: (context, counter, child) {
return Text('计数器: ${counter.count}');
},
);
}
}

class CounterButtons extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 方式2: 使用 Provider.of
final counter = Provider.of<CounterModel>(context);

return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: counter.decrement,
child: Text('-'),
),
SizedBox(width: 20),
ElevatedButton(
onPressed: counter.increment,
child: Text('+'),
),
],
);
}
}

// 方式3: 使用 Selector(性能优化)
class OptimizedDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Selector<CounterModel, int>(
selector: (context, counter) => counter.count,
builder: (context, count, child) {
return Text('计数器: $count');
},
);
}
}

2. 多 Model 管理

dart 复制代码
// 用户 Model
class UserModel with ChangeNotifier {
String _name = '张三';
int _age = 25;

String get name => _name;
int get age => _age;

void updateUser(String newName, int newAge) {
_name = newName;
_age = newAge;
notifyListeners();
}
}

// 主题 Model
class ThemeModel with ChangeNotifier {
bool _isDark = false;

bool get isDark => _isDark;
ThemeData get theme => _isDark ? ThemeData.dark() : ThemeData.light();

void toggleTheme() {
_isDark = !_isDark;
notifyListeners();
}
}

// 应用入口
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserModel()),
ChangeNotifierProvider(create: (_) => ThemeModel()),
ChangeNotifierProvider(create: (_) => CounterModel()),
],
child: MyApp(),
),
);
}

// 使用多个 Provider
class ProfilePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final user = Provider.of<UserModel>(context);
final theme = Provider.of<ThemeModel>(context);

return Scaffold(
appBar: AppBar(
title: Text('个人资料'),
backgroundColor: theme.isDark ? Colors.black : Colors.blue,
),
body: Center(
child: Column(
children: [
Text('姓名: ${user.name}'),
Text('年龄: ${user.age}'),
Switch(
value: theme.isDark,
onChanged: (_) => theme.toggleTheme(),
),
],
),
),
);
}
}

3. FutureProvider 和 StreamProvider

dart 复制代码
// FutureProvider 示例
class DataService {
Future<String> fetchData() async {
await Future.delayed(Duration(seconds: 2));
return '加载的数据';
}
}

void main() {
runApp(
MultiProvider(
providers: [
Provider(create: (_) => DataService()),
FutureProvider<String>(
create: (context) => context.read<DataService>().fetchData(),
initialData: '正在加载...',
),
],
child: MyApp(),
),
);
}

class DataDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
final data = context.watch<String>();

return Center(
child: Text(data),
);
}
}

// StreamProvider 示例
class TimerService {
Stream<int> get timerStream => Stream.periodic(
Duration(seconds: 1),
(count) => count,
).take(10);
}

void main() {
runApp(
Provider(
create: (_) => TimerService(),
child: StreamProvider<int>(
create: (context) => context.read<TimerService>().timerStream,
initialData: 0,
child: MyApp(),
),
),
);
}

class TimerDisplay extends StatelessWidget {
@override
Widget build(BuildContext context) {
final seconds = context.watch<int>();

return Center(
child: Text('已过去 $seconds 秒'),
);
}
}

四、Riverpod(Provider 的改进版)

1. Riverpod 基础

yaml 复制代码
# pubspec.yaml
dependencies:
flutter_riverpod: ^2.0.0
dart 复制代码
// 1. 创建 Provider
final counterProvider = StateProvider<int>((ref) => 0);

// 2. 使用 ConsumerWidget
class CounterApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);

return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('计数器: $count'),
ElevatedButton(
onPressed: () => ref.read(counterProvider.notifier).state++,
child: Text('增加'),
),
],
),
),
);
}
}

// 3. 使用 ConsumerStatefulWidget
class CounterPage extends ConsumerStatefulWidget {
@override
ConsumerState<CounterPage> createState() => _CounterPageState();
}

class _CounterPageState extends ConsumerState<CounterPage> {
@override
Widget build(BuildContext context) {
final count = ref.watch(counterProvider);

return Scaffold(
body: Center(
child: Text('计数器: $count'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ref.read(counterProvider.notifier).state++;
},
child: Icon(Icons.add),
),
);
}
}

2. Riverpod 进阶用法

dart 复制代码
// 异步 Provider
final userProvider = FutureProvider<String>((ref) async {
await Future.delayed(Duration(seconds: 2));
return '张三';
});

// 组合 Provider
final authProvider = Provider<AuthService>((ref) => AuthService());
final userInfoProvider = FutureProvider<User>((ref) async {
final auth = ref.watch(authProvider);
return await auth.getCurrentUser();
});

// 状态通知 Provider
final counterNotifierProvider = StateNotifierProvider<CounterNotifier, int>(
(ref) => CounterNotifier(),
);

class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);

void increment() => state++;
void decrement() => state--;
}

// 使用
class CounterWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterNotifierProvider);
final notifier = ref.read(counterNotifierProvider.notifier);

return Column(
children: [
Text('计数器: $count'),
ElevatedButton(
onPressed: notifier.increment,
child: Text('增加'),
),
],
);
}
}

五、GetX(轻量高效)

1. GetX 基础使用

yaml 复制代码
# pubspec.yaml
dependencies:
get: ^4.6.0
dart 复制代码
// 1. 创建 Controller
class CounterController extends GetxController {
var count = 0.obs; // 响应式变量

void increment() => count.value++;
void decrement() => count.value--;
}

// 2. 使用 GetView(推荐)
class CounterPage extends GetView<CounterController> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Obx(() => Text('计数器: ${controller.count}')),
),
floatingActionButton: FloatingActionButton(
onPressed: controller.increment,
child: Icon(Icons.add),
),
);
}
}

// 3. 绑定 Controller
void main() {
runApp(GetMaterialApp(
home: CounterPage(),
initialBinding: BindingsBuilder(() {
Get.put(CounterController());
}),
));
}

// 或者使用 GetBuilder
class CounterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetBuilder<CounterController>(
init: CounterController(),
builder: (controller) {
return Column(
children: [
Text('计数器: ${controller.count}'),
ElevatedButton(
onPressed: controller.increment,
child: Text('增加'),
),
],
);
},
);
}
}

2. GetX 路由和依赖注入

dart 复制代码
// 1. 路由管理
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('首页')),
body: Center(
child: ElevatedButton(
child: Text('跳转到详情'),
onPressed: () {
Get.to(
() => DetailPage(),
arguments: {'id': 123},
transition: Transition.rightToLeft,
duration: Duration(milliseconds: 300),
);
},
),
),
);
}
}

// 2. 详情页获取参数
class DetailPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final args = Get.arguments;

return Scaffold(
appBar: AppBar(title: Text('详情页')),
body: Center(child: Text('ID: ${args['id']}')),
);
}
}

// 3. 依赖注入
class ApiService {
Future<String> fetchData() async => '数据';
}

class HomeController extends GetxController {
final ApiService apiService = Get.find();
var data = ''.obs;

@override
void onInit() {
super.onInit();
loadData();
}

void loadData() async {
data.value = await apiService.fetchData();
}
}

// 4. 全局绑定
void main() {
runApp(GetMaterialApp(
initialBinding: AppBindings(),
home: HomePage(),
));
}

class AppBindings extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => ApiService(), fenix: true);
Get.lazyPut(() => HomeController());
}
}

六、BLoC/Cubit

1. Cubit 基础

yaml 复制代码
# pubspec.yaml
dependencies:
flutter_bloc: ^8.0.0
dart 复制代码
// 1. 创建 Cubit
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);

void increment() => emit(state + 1);
void decrement() => emit(state - 1);
}

// 2. 提供 Cubit
void main() {
runApp(
BlocProvider(
create: (context) => CounterCubit(),
child: MyApp(),
),
);
}

// 3. 使用 BlocBuilder
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: BlocBuilder<CounterCubit, int>(
builder: (context, count) {
return Text('计数器: $count');
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<CounterCubit>().increment(),
child: Icon(Icons.add),
),
);
}
}

// 4. 使用 BlocConsumer
class CounterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocConsumer<CounterCubit, int>(
listener: (context, state) {
// 状态变化时执行
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('计数器变为: $state')),
);
},
builder: (context, state) {
return Column(
children: [
Text('计数器: $state'),
ElevatedButton(
onPressed: () => context.read<CounterCubit>().increment(),
child: Text('增加'),
),
],
);
},
);
}
}

2. BLoC 完整示例

dart 复制代码
// 1. 定义事件
abstract class CounterEvent {}

class IncrementEvent extends CounterEvent {}
class DecrementEvent extends CounterEvent {}

// 2. 创建 BLoC
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<IncrementEvent>((event, emit) => emit(state + 1));
on<DecrementEvent>((event, emit) => emit(state - 1));
}
}

// 3. 使用
class BlocCounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CounterBloc(),
child: Scaffold(
body: Center(
child: BlocBuilder<CounterBloc, int>(
builder: (context, count) {
return Text('计数器: $count');
},
),
),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(IncrementEvent()),
child: Icon(Icons.add),
),
SizedBox(height: 10),
FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(DecrementEvent()),
child: Icon(Icons.remove),
),
],
),
),
);
}
}

七、MobX

1. MobX 基础

yaml 复制代码
# pubspec.yaml
dependencies:
mobx: ^2.0.0
flutter_mobx: ^2.0.0

dev_dependencies:
build_runner: ^2.0.0
mobx_codegen: ^2.0.0
dart 复制代码
// counter_store.dart
import 'package:mobx/mobx.dart';

part 'counter_store.g.dart';

class CounterStore = _CounterStore with _$CounterStore;

abstract class _CounterStore with Store {
@observable
int count = 0;

@action
void increment() {
count++;
}

@action
void decrement() {
count--;
}

@computed
bool get isEven => count % 2 == 0;
}

// 运行命令生成代码
// flutter pub run build_runner build

// 使用
class CounterPage extends StatelessWidget {
final CounterStore store = CounterStore();

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Observer(
builder: (_) => Text('计数器: ${store.count}'),
),
Observer(
builder: (_) => Text(store.isEven ? '偶数' : '奇数'),
),
ElevatedButton(
onPressed: store.increment,
child: Text('增加'),
),
],
),
),
);
}
}

八、状态管理方案对比

方案 优点 缺点 适用场景
setState 简单易用,无额外依赖 不适合复杂状态,性能较差 简单组件,局部状态
Provider 官方推荐,学习曲线平缓 需要手动管理依赖 中小型应用,团队协作
Riverpod Provider 改进版,编译安全 相对较新,社区较小 需要类型安全的中大型应用
GetX 功能全面,开发效率高 框架耦合度较高 快速开发,个人项目
BLoC 分离业务逻辑,可测试性强 样板代码较多 企业级应用,复杂业务逻辑
MobX 响应式,代码简洁 需要代码生成 熟悉响应式编程的团队

九、最佳实践

1. 状态分层

dart 复制代码
// 1. 本地状态(使用 setState)
class LocalStateWidget extends StatefulWidget {
@override
_LocalStateWidgetState createState() => _LocalStateWidgetState();
}

// 2. 应用状态(使用 Provider/GetX/BLoC)
class AppState {
final UserModel user;
final SettingsModel settings;
final CartModel cart;

AppState({
required this.user,
required this.settings,
required this.cart,
});
}

// 3. 服务层(处理网络请求等)
class ApiService {
Future<User> fetchUser() async {
// 网络请求
}
}

2. 性能优化

dart 复制代码
// 使用 const 构造函数
class MyWidget extends StatelessWidget {
const MyWidget({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return const Text('Hello');
}
}

// 使用 ValueKey
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return ListTile(
key: ValueKey(items[index].id), // 使用唯一标识
title: Text(items[index].name),
);
},
);

// 使用 AutomaticKeepAliveClientMixin
class KeepAlivePage extends StatefulWidget {
@override
_KeepAlivePageState createState() => _KeepAlivePageState();
}

class _KeepAlivePageState extends State<KeepAlivePage>
with AutomaticKeepAliveClientMixin {

@override
bool get wantKeepAlive => true; // 保持状态

@override
Widget build(BuildContext context) {
super.build(context);
return Container();
}
}

3. 测试状态管理

dart 复制代码
// 测试 CounterCubit
void main() {
group('CounterCubit', () {
late CounterCubit counterCubit;

setUp(() {
counterCubit = CounterCubit();
});

tearDown(() {
counterCubit.close();
});

test('初始状态为0', () {
expect(counterCubit.state, 0);
});

test('增加操作', () {
counterCubit.increment();
expect(counterCubit.state, 1);
});
});
}

十、选择建议

  1. 新手入门 :从 setStateProvider 开始
  2. 中小项目 :使用 ProviderGetX
  3. 大型项目 :考虑 BLoCRiverpod
  4. 快速开发GetX 是很好的选择
  5. 需要强类型 :选择 Riverpod
  6. 响应式编程爱好者 :尝试 MobX

记住:没有最好的状态管理方案,只有最适合你项目需求的方案。根据项目规模、团队经验和具体需求来选择。

相关推荐
yangyanping2010818 小时前
Go语言学习之对象关系映射GORM
jvm·学习·golang
这是个栗子18 小时前
TypeScript(三)
前端·javascript·typescript·react
网络工程小王18 小时前
【Transformer架构详解】(学习笔记)
笔记·学习
倒酒小生20 小时前
今日算法学习小结
学习
醇氧21 小时前
【学习】【说人话版】子网划分
学习
前端精髓21 小时前
移除 Effect 依赖
前端·javascript·react.js
不灭锦鲤1 天前
网络安全学习(面试)
学习·安全·web安全
lpfasd1231 天前
TypeScript + Cloudflare 全家桶部署项目全流程
前端·javascript·typescript
前端Hardy1 天前
字节/腾讯内部流出!Claude Code 2026王炸玩法!效率暴涨10倍
前端·javascript·vue.js
世人万千丶1 天前
Flutter 框架跨平台鸿蒙开发 - 鸿蒙版本五子棋游戏应用
学习·flutter·游戏·华为·harmonyos·鸿蒙