一、引言

在 Flutter 开发中,状态管理(State Management) 是绕不开的核心话题。随着应用复杂度提升,简单的 setState 已无法满足需求。目前主流方案包括 Provider、Riverpod、Bloc 等。本文将通过一个“待办事项(Todo)”应用,对比三种方案的写法、性能与适用场景,并给出选型建议。


二、为什么需要状态管理?

  • 避免组件间频繁传递回调
  • 实现数据共享与响应式更新
  • 提升代码可维护性与可测试性


图:无状态管理 vs 有状态管理的数据流对比


三、方案一:Provider(官方推荐入门方案)

✅ 优点:

  • 官方支持,学习曲线平缓
  • 基于 InheritedWidget,性能良好

📦 添加依赖(pubspec.yaml):

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.1.0

💡 示例代码(Todo 列表):编辑

// todo_model.dart
class Todo {
  final String title;
  bool completed;
  Todo(this.title, {this.completed = false});
}

// todo_provider.dart
class TodoProvider with ChangeNotifier {
  final List<Todo> _todos = [];

  List<Todo> get todos => _todos;

  void addTodo(String title) {
    _todos.add(Todo(title));
    notifyListeners();
  }

  void toggle(int index) {
    _todos[index].completed = !_todos[index].completed;
    notifyListeners();
  }
}

// main.dart
void main() {
  runApp(
    ChangeNotifierProvider(
      create: (_) => TodoProvider(),
      child: const MyApp(),
    ),
  );
}

// 在 UI 中使用
Consumer<TodoProvider>(
  builder: (context, todoProvider, child) {
    return ListView.builder(
      itemCount: todoProvider.todos.length,
      itemBuilder: (context, i) => CheckboxListTile(
        title: Text(todoProvider.todos[i].title),
        value: todoProvider.todos[i].completed,
        onChanged: (_) => todoProvider.toggle(i),
      ),
    );
  },
)

四、方案二:Riverpod(Provider 的现代化升级)

✅ 优点:

  • 不依赖 BuildContext
  • 支持编译时安全、异步状态、组合 Provider
  • 更适合大型项目

📦 依赖:


dependencies:
  flutter_riverpod: ^2.5.0

💡 示例代码:


final todoProvider = StateNotifierProvider<TodoNotifier, List<Todo>>((ref) {
  return TodoNotifier();
});

class TodoNotifier extends StateNotifier<List<Todo>> {
  TodoNotifier() : super([]);

  void add(String title) {
    state = [...state, Todo(title)];
  }

  void toggle(int index) {
    state = [
      for (int i = 0; i < state.length; i++)
        if (i == index)
          Todo(state[i].title, completed: !state[i].completed)
        else
          state[i]
    ];
  }
}

// UI 中使用(无需 Consumer)
@override
Widget build(BuildContext context, WidgetRef ref) {
  final todos = ref.watch(todoProvider);

  return ListView.builder(
    itemCount: todos.length,
    itemBuilder: (context, i) => CheckboxListTile(
      title: Text(todos[i].title),
      value: todos[i].completed,
      onChanged: (_) => ref.read(todoProvider.notifier).toggle(i),
    ),
  );
}

✅ 优势:即使在 showDialog 或静态方法中也能访问状态!


五、方案三:Bloc(事件驱动,适合复杂业务)

✅ 优点:

  • 清晰分离逻辑与 UI
  • 强类型、可测试性强
  • 适合金融、电商等高复杂度场景

📦 依赖:

dependencies:
  flutter_bloc: ^8.1.0

💡 核心结构:

  • Event:用户操作(如 AddTodo)
  • Bloc:处理逻辑
  • State:UI 状态(如 Loading / Success)
// todo_bloc.dart
class TodoBloc extends Bloc<TodoEvent, TodoState> {
  final List<Todo> _todos = [];

  TodoBloc() : super(TodoInitial()) {
    on<AddTodo>((event, emit) {
      _todos.add(Todo(event.title));
      emit(TodoLoaded(_todos));
    });
  }
}

⚠️ 编写量较大,但逻辑极其清晰。


六、三大方案对比总结

方案 学习成本 适用场景 是否依赖 Context 异步支持
Provider 中小型项目 一般
Riverpod 中大型项目 否 ✅
Bloc 复杂业务/团队协作 极强

七、结语

  • 新手推荐:从 Provider 入手
  • 进阶项目:优先考虑 Riverpod
  • 企业级应用:Bloc + Clean Architecture

GitHub 示例仓库:github.com/yourname/flutter-state-compare

欢迎在评论区讨论你用的状态管理方案!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐