在 Flutter 中,状态管理是开发复杂应用的核心。随着应用规模的增长,管理状态变得越来越重要。无论是简单的局部状态,还是复杂的全局状态,选择合适的状态管理方案可以显著提高开发效率和代码可维护性。
本篇博客将详细分析 Flutter 状态管理的核心概念、常见方案(如 setState
、Provider
、Riverpod
、Bloc
等),并结合实际场景进行实战演示。
setState
class CounterApp extends StatefulWidget {
_CounterAppState createState() => _CounterAppState();
}
class _CounterAppState extends State<CounterApp> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("setState 示例")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("点击次数:$_counter"),
ElevatedButton(
onPressed: _incrementCounter,
child: Text("增加计数"),
),
],
),
),
);
}
}
InheritedWidget
class CounterProvider extends InheritedWidget {
final int counter;
final Function() increment;
CounterProvider({
required this.counter,
required this.increment,
required Widget child,
}) : super(child: child);
static CounterProvider? of(BuildContextContext context) {
return context.dependOnInheritedWidgetOfExactType<CounterProvider>();
}
bool updateShouldNotify(CounterProvider oldWidget) {
return oldWidget.counter != counter;
}
}
class CounterApp extends StatefulWidget {
_CounterAppState createState() => _CounterAppState();
}
class _CounterAppState extends State<CounterApp> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
Widget build(BuildContext context) {
return CounterProvider(
counter: _counter,
increment: _incrementCounter,
child: CounterHomePage(),
);
}
}
class CounterHomePage extends StatelessWidget {
Widget build(BuildContext context) {
final provider = CounterProvider.of(context);
return Scaffold(
appBar: AppBar(title: Text("InheritedWidget 示例")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("点击次数:${provider?.counter}"),
ElevatedButton(
onPressed: provider?.increment,
child: Text("增加计数"),
),
],
),
),
);
}
}
Provider
InheritedWidget
,简化了状态共享的代码。在 pubspec.yaml
中添加依赖:
dependencies:
provider: ^6.0.0
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Counter with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Counter(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: CounterHomePage(),
);
}
}
class CounterHomePage extends StatelessWidget {
Widget build(BuildContext context) {
final counter = Provider.of<Counter>(context);
return Scaffold(
appBar: AppBar(title: Text("Provider 示例")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("点击次数:${counter.count}"),
ElevatedButton(
onPressed: counter.increment,
child: Text("增加计数"),
),
],
),
),
);
}
}
ChangeNotifier
和 Consumer
的用法。Riverpod
Provider
的升级版,支持更好的类型安全和全局状态管理。BuildContext
,更灵活。在 pubspec.yaml
中添加依赖:
dependencies:
flutter_riverpod: ^2.0.0
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
final counterProvider = StateProvider<int>((ref) => 0);
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: CounterHomePage(),
);
}
}
class CounterHomePage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final counter = ref.watch(counterProvider);
return Scaffold(
appBar: AppBar(title: Text("Riverpod 示例")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("点击次数:$counter"),
ElevatedButton(
onPressed: () => ref.read(counterProvider.notifier).state++,
child: Text("增加计数"),
),
],
),
),
);
}
}
BuildContext
,更灵活。Bloc
在 pubspec.yaml
中添加依赖:
dependencies:
flutter_bloc: ^8.0.0
bloc: ^8.0.0
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
}
void main() {
runApp(
BlocProvider(
create: (context) => CounterCubit(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: CounterHomePage(),
);
}
}
class CounterHomePage extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Bloc 示例")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
BlocBuilder<CounterCubit, int>(
builder: (context, count) {
return Text("点击次数:$count");
},
),
ElevatedButton(
onPressed: () => context.read<CounterCubit>().increment(),
child: Text("增加计数"),
),
],
),
),
);
}
}
Provider
实现import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Cart with ChangeNotifier {
final List<String> _items = [];
List<String> get items => _items;
void addItem(String item) {
_items.add(item);
notifyListeners();
}
void removeItem(String item) {
_items.remove(item);
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => Cart(),
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: ProductListPage(),
);
}
}
class ProductListPage extends StatelessWidget {
Widget build(BuildContext context) {
final cart = Provider.of<Cart>(context);
return Scaffold(
appBar: AppBar(
title: Text("商品列表"),
actions: [
IconButton(
icon: Icon(Icons.shopping_cart),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CartPage()),
);
},
),
],
),
body: ListView(
children: [
for (var product in ["商品 1", "商品 2", "商品 3"])
ListTile(
title: Text(product),
trailing: ElevatedButton(
onPressed: () => cart.addItem(product),
child: Text("添加到购物车"),
),
),
],
),
);
}
}
class CartPage extends StatelessWidget {
Widget build(BuildContext context) {
final cart = Provider.of<Cart>(context);
return Scaffold(
appBar: AppBar(title: Text("购物车")),
body: ListView(
children: [
for (var item in cart.items)
ListTile(
title: Text(item),
trailing: ElevatedButton(
onPressed: () => cart.removeItem(item),
child: Text("删除"),
),
),
],
),
);
}
}
方案 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
setState |
局部状态管理 | 简单易用 | 不适合全局状态 |
InheritedWidget |
状态共享 | 内置支持 | 使用复杂 |
Provider |
全局状态管理 | 简单易用,性能高 | 需要学习 ChangeNotifier |
Riverpod |
全局状态管理 | 类型安全,灵活 | 学习曲线较高 |
Bloc |
复杂业务逻辑 | 状态可追踪,适合大型项目 | 学习曲线高,代码冗长 |
setState
或 Provider
。Provider
或 Riverpod
。Bloc
或 Riverpod
。通过本篇博客,你应该能够根据项目需求选择合适的状态管理方案,并在实际开发中灵活应用这些技术!