2026/1/8 16:55:12
网站建设
项目流程
做计量检定的网站,wordpress加导航菜单,深圳人才市场招聘网最新招聘信息,广州哪里可以做网站目录
引言#xff1a;状态管理为何是 Flutter 开发的核心痛点Provider#xff1a;基于 InheritedWidget 的经典状态管理方案2.1 Provider 核心原理2.2 Provider 实战#xff1a;基础 Todo 列表实现Riverpod#xff1a;Provider 的 “升级版” 核心改进3.1 Riverpod 核心优…目录引言状态管理为何是 Flutter 开发的核心痛点Provider基于 InheritedWidget 的经典状态管理方案2.1 Provider 核心原理2.2 Provider 实战基础 Todo 列表实现RiverpodProvider 的 “升级版” 核心改进3.1 Riverpod 核心优势3.2 Riverpod 实战重构 Todo 列表Provider vs Riverpod核心对比与选型建议总结正文1. 引言状态管理为何是 Flutter 开发的核心痛点Flutter 的 “单向数据流” 设计让状态管理成为开发中绕不开的话题 —— 小到按钮的点击状态大到跨页面的用户信息如何高效、可维护地管理状态直接决定了项目的开发效率和可扩展性。Provider 作为 Flutter 生态中最主流的状态管理方案之一凭借 “低学习成本 贴合 Flutter 原生设计” 的特点成为入门首选而 Riverpod 作为 Provider 作者的全新重构版本解决了 Provider 的上下文依赖、类型安全等痛点逐渐成为进阶开发的新选择。本文将从核心原理入手结合实战案例对比两者的实现方式帮助你理解底层逻辑并做出适合自己项目的选型。2. Provider基于 InheritedWidget 的经典状态管理方案2.1 Provider 核心原理Provider 的底层是 Flutter 原生的InheritedWidget—— 这是一种能让子 Widget 跨层级获取父 Widget 数据的机制核心逻辑是状态持有者如ChangeNotifier封装业务数据和状态变更方法通过Provider/ChangeNotifierProvider将状态注入 Widget 树子 Widget 通过Consumer/Provider.of监听状态变化触发重建。ChangeNotifier是 Provider 的核心状态载体它继承自Listenable通过notifyListeners()方法通知所有监听者状态变更。2.2 Provider 实战基础 Todo 列表实现第一步定义 Todo 模型和状态管理类// todo_model.dart class Todo { final String id; final String title; final bool isCompleted; Todo({ required this.id, required this.title, this.isCompleted false, }); // 复制方法用于修改状态 Todo copyWith({String? id, String? title, bool? isCompleted}) { return Todo( id: id ?? this.id, title: title ?? this.title, isCompleted: isCompleted ?? this.isCompleted, ); } } // todo_provider.dart import package:flutter/foundation.dart; import package:uuid/uuid.dart; import todo_model.dart; class TodoProvider extends ChangeNotifier { final ListTodo _todos []; // 获取只读的todo列表 ListTodo get todos List.unmodifiable(_todos); // 添加todo void addTodo(String title) { if (title.isEmpty) return; _todos.add(Todo( id: const Uuid().v4(), title: title, )); notifyListeners(); // 通知监听者更新 } // 切换todo完成状态 void toggleTodo(String id) { final index _todos.indexWhere((todo) todo.id id); if (index -1) return; _todos[index] _todos[index].copyWith(isCompleted: !_todos[index].isCompleted); notifyListeners(); } // 删除todo void deleteTodo(String id) { _todos.removeWhere((todo) todo.id id); notifyListeners(); } }第二步在 Widget 树中注入 Provider 并实现 UI// main.dart import package:flutter/material.dart; import package:provider/provider.dart; import todo_provider.dart; void main() { runApp( // 将TodoProvider注入Widget树 ChangeNotifierProvider( create: (context) TodoProvider(), child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); override Widget build(BuildContext context) { return MaterialApp( title: Provider Todo Demo, theme: ThemeData(primarySwatch: Colors.blue), home: const TodoPage(), ); } } class TodoPage extends StatelessWidget { const TodoPage({super.key}); override Widget build(BuildContext context) { final todoProvider Provider.ofTodoProvider(context); final TextEditingController _controller TextEditingController(); return Scaffold( appBar: AppBar(title: const Text(Provider Todo List)), body: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ Expanded( child: TextField( controller: _controller, decoration: const InputDecoration(hintText: 输入待办事项), ), ), ElevatedButton( onPressed: () { todoProvider.addTodo(_controller.text); _controller.clear(); }, child: const Text(添加), ), ], ), ), Expanded( // Consumer仅重建列表避免整个页面重建 child: ConsumerTodoProvider( builder: (context, provider, child) { return ListView.builder( itemCount: provider.todos.length, itemBuilder: (context, index) { final todo provider.todos[index]; return ListTile( title: Text( todo.title, style: TextStyle( decoration: todo.isCompleted ? TextDecoration.lineThrough : TextDecoration.none, ), ), leading: Checkbox( value: todo.isCompleted, onChanged: (value) provider.toggleTodo(todo.id), ), trailing: IconButton( icon: const Icon(Icons.delete, color: Colors.red), onPressed: () provider.deleteTodo(todo.id), ), ); }, ); }, ), ), ], ), ); } }3. RiverpodProvider 的 “升级版” 核心改进3.1 Riverpod 核心优势Provider 的核心痛点强依赖 BuildContext无法在 Widget 外获取状态类型不安全相同类型的 Provider 会冲突无法轻松实现多实例状态管理。Riverpod 的核心改进完全脱离 BuildContext状态通过 “Provider” 对象直接管理类型安全每个 Provider 有唯一标识支持多实例、缓存、自动刷新等高级特性内置多种 Provider 类型StateProvider、NotifierProvider、FutureProvider 等。3.2 Riverpod 实战重构 Todo 列表第一步配置 Riverpod 环境需先安装依赖flutter pub add flutter_riverpod// main.dart 入口配置 import package:flutter_riverpod/flutter_riverpod.dart; void main() { // 必须用ProviderScope包裹根Widget runApp(const ProviderScope(child: MyApp())); }第二步定义 Riverpod 状态管理类// todo_riverpod.dart import package:flutter_riverpod/flutter_riverpod.dart; import package:uuid/uuid.dart; import todo_model.dart; // 定义Notifier类封装业务逻辑 class TodoNotifier extends NotifierListTodo { // 初始化状态 override ListTodo build() []; // 添加todo void addTodo(String title) { if (title.isEmpty) return; state [ ...state, Todo( id: const Uuid().v4(), title: title, ), ]; } // 切换完成状态 void toggleTodo(String id) { state state.map((todo) { if (todo.id id) { return todo.copyWith(isCompleted: !todo.isCompleted); } return todo; }).toList(); } // 删除todo void deleteTodo(String id) { state state.where((todo) todo.id ! id).toList(); } } // 定义Provider全局可访问无需上下文 final todoProvider NotifierProviderTodoNotifier, ListTodo(() { return TodoNotifier(); });第三步实现 UI无上下文依赖// todo_riverpod_page.dart import package:flutter/material.dart; import package:flutter_riverpod/flutter_riverpod.dart; import todo_riverpod.dart; class TodoRiverpodPage extends ConsumerWidget { const TodoRiverpodPage({super.key}); override Widget build(BuildContext context, WidgetRef ref) { // 监听状态变化ref.watch自动重建 final ListTodo todos ref.watch(todoProvider); final TextEditingController _controller TextEditingController(); // 获取Notifier用于调用方法不会触发重建 final TodoNotifier todoNotifier ref.read(todoProvider.notifier); return Scaffold( appBar: AppBar(title: const Text(Riverpod Todo List)), body: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ Expanded( child: TextField( controller: _controller, decoration: const InputDecoration(hintText: 输入待办事项), ), ), ElevatedButton( onPressed: () { todoNotifier.addTodo(_controller.text); _controller.clear(); }, child: const Text(添加), ), ], ), ), Expanded( child: ListView.builder( itemCount: todos.length, itemBuilder: (context, index) { final todo todos[index]; return ListTile( title: Text( todo.title, style: TextStyle( decoration: todo.isCompleted ? TextDecoration.lineThrough : TextDecoration.none, ), ), leading: Checkbox( value: todo.isCompleted, onChanged: (value) todoNotifier.toggleTodo(todo.id), ), trailing: IconButton( icon: const Icon(Icons.delete, color: Colors.red), onPressed: () todoNotifier.deleteTodo(todo.id), ), ); }, ), ), ], ), ); } }4. Provider vs Riverpod核心对比与选型建议维度ProviderRiverpod上下文依赖强依赖 BuildContext完全脱离上下文类型安全弱相同类型易冲突强唯一标识多实例支持复杂需手动管理原生支持family 修饰符监听方式Provider.of/Consumer/Selectorref.watch/ref.read/ref.listen错误处理需手动捕获内置错误处理when/ifLoading学习成本低中等新增概念Ref、ProviderScope选型建议小型项目 / 快速原型优先 Provider学习成本低足够满足需求中大型项目 / 团队协作优先 Riverpod类型安全、可维护性更高跨 Widget / 异步场景Riverpod 的 FutureProvider/StreamProvider 更易用。5. 总结Provider 和 Riverpod 本质都是围绕 “状态共享 监听变更” 的核心设计区别在于 Riverpod 解决了 Provider 的历史痛点提供了更优雅的 API 和更强的扩展性。无论选择哪种方案核心原则都是最小化状态范围 避免不必要的重建—— 这也是 Flutter 状态管理的核心思想。https://openharmonycrossplatform.csdn.net/content欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net)一起共建开源鸿蒙跨平台生态。