01. StatefulWidget 和 setState
Flutter 中一切皆 Widget。StatelessWidget 是不可变的(属性不能改),StatefulWidget 是可变的(有内部状态)。StatefulWidget 有两个类:Widget 类和 State 类。调用 setState 通知框架重绘。setState 里改数据,Flutter 自动 diff 并高效更新 UI。这是最基本的状态管理方式。
dart
import 'package:flutter/material.dart';
class CounterWidget extends StatefulWidget {
@override
_CounterWidgetState createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _count = 0;
void _increment() {
setState(() {
_count++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('计数: $_count', style: TextStyle(fontSize: 24)),
ElevatedButton(
onPressed: _increment,
child: Text('加一'),
),
],
);
}
}setState 只重建当前 State 对应的 build,不会重建整个页面,Flutter 的 diff 机制非常高效。
02. InheritedWidget 和上下传递
InheritedWidget 能沿着 Widget 树向下传递数据,子 Widget 不需要一层层通过构造函数传参。典型的用法是 Theme.of(context) 获取主题、MediaQuery.of(context) 获取屏幕尺寸。原理是子 Widget 通过 BuildContext 向上查找最近的 InheritedWidget。
dart
class MyInherited extends InheritedWidget {
final int data;
MyInherited({required this.data, required Widget child}) : super(child: child);
static MyInherited? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInherited>();
}
@override
bool updateShouldNotify(MyInherited oldWidget) => data != oldWidget.data;
}
// 使用
class ChildWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final data = MyInherited.of(context)?.data ?? 0;
return Text('数据: $data');
}
}InheritedWidget 是底层 API,实际开发不直接用它。Provider 库在 InheritedWidget 上做了更友好的封装。
03. Provider 状态管理
Provider 是 Flutter 团队推荐的状态管理方案,底层基于 InheritedWidget。ChangeNotifier 是可监听的数据模型,notifyListeners() 通知刷新。ChangeNotifierProvider 把数据注入 Widget 树,Consumer 或 context.watch 获取数据并自动更新。是目前最主流的方式。
dart
import 'package:provider/provider.dart';
// 数据模型
class CounterModel extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
// 注入
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => CounterModel(),
child: MyApp(),
),
);
}
// 使用
class CounterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counter = context.watch<CounterModel>();
return Column(
children: [
Text('计数: ${counter.count}'),
ElevatedButton(
onPressed: () => context.read<CounterModel>().increment(),
child: Text('加一'),
),
],
);
}
}context.watch 会监听变化自动重建,context.read 只读不监听,用于回调里。搞混了会多重建。
04. Riverpod 新一代状态管理
Riverpod 是 Provider 的升级版,解决了 Provider 的一些痛点(编译时安全、不依赖 BuildContext、支持多个同类型 Provider)。Provider 通过函数创建全局可访问的数据容器,ref 访问其他 Provider。StatelessWidget 配合 ConsumerWidget 获取数据。
dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
// 定义 Provider
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
return CounterNotifier();
});
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);
void increment() => state++;
}
// 使用
class CounterPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Scaffold(
body: Center(
child: Text('$count', style: TextStyle(fontSize: 48)),
),
floatingActionButton: FloatingActionButton(
onPressed: () => ref.read(counterProvider.notifier).increment(),
child: Icon(Icons.add),
),
);
}
}Riverpod 最大的优势是不依赖 BuildContext,可以在任何地方访问 Provider,包括测试代码。
05. BLoC 模式
BLoC 是更正式的状态管理方案,把业务逻辑从 UI 完全分离。事件进(Events)状态出(States),中间 BLoC 处理。使用了 Stream 流式架构。flutter_bloc 库提供了 BlocProvider 注入、BlocBuilder 重建、BlocListener 监听副作用。适合大型项目和团队协作。
dart
import 'package:flutter_bloc/flutter_bloc.dart';
// 事件
abstract class CounterEvent {}
class Increment extends CounterEvent {}
// BLoC
class CounterBloc extends Bloc<CounterEvent, int> {
CounterBloc() : super(0) {
on<Increment>((event, emit) => emit(state + 1));
}
}
// 界面
class CounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterBloc(),
child: Scaffold(
body: Center(
child: BlocBuilder<CounterBloc, int>(
builder: (context, count) => Text('$count', style: TextStyle(fontSize: 48)),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<CounterBloc>().add(Increment()),
child: Icon(Icons.add),
),
),
);
}
}BLoC 强制将 UI 和业务逻辑分离,虽然模板代码多了点,但可测试性和可维护性大幅提升。
知识测验
第 1/4 题正确 0
Flutter 中 setState 的作用?
下一节
下一节 导航与路由