Flutter 状态路径一次性描述
看来新的项目有用到之前没用过的库,所以需要了解一下。
各个状态库描述
riverpod,riverpod-annotation,flutter hook,hooks-riverpod 这些有没有类似递进的关系,这样的话,我好一步一步了解,你也可以补充我漏掉的环节
让我帮你梳理这些库的递进关系和学习路径:
-
riverpod
(基础库)- 这是最基础的库,提供了核心的状态管理功能
- 主要概念:Provider, StateNotifier, ProviderContainer
// 基础写法 final counterProvider = StateNotifierProvider<Counter, int>((ref) { return Counter(); }); class Counter extends StateNotifier<int> { Counter() : super(0); void increment() => state++; }
-
flutter_riverpod
(Flutter 集成)- 在
riverpod
基础上增加了 Flutter 集成 - 提供了 ConsumerWidget, ConsumerStatefulWidget 等
class MyWidget extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(counterProvider); return Text('$count'); } }
- 在
-
riverpod_annotation
(简化语法)- 通过代码生成简化 Provider 的创建
- 引入了 @riverpod 注解
class Counter extends _$Counter { int build() => 0; void increment() => state++; }
-
flutter_hooks
(状态逻辑复用)- 提供了一种新的状态管理方式
- 主要用于复用状态逻辑
class Example extends HookWidget { Widget build(BuildContext context) { final controller = useTextEditingController(); return TextField(controller: controller); } }
-
hooks_riverpod
(完整集成)- 结合了
flutter_riverpod
和flutter_hooks
- 提供了 HookConsumerWidget 等组件
class Example extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final controller = useTextEditingController(); final count = ref.watch(counterProvider); return TextField(controller: controller); } }
- 结合了
学习建议:
- 先学习
riverpod
的核心概念 - 了解
flutter_riverpod
如何与 Flutter 集成 - 学习使用
riverpod_annotation
简化代码 - 如果需要处理复杂状态逻辑,学习
flutter_hooks
- 最后掌握
hooks_riverpod
的完整功能
补充一些重要的中间环节:
-
Provider 的不同类型:
- Provider
- StateProvider
- StateNotifierProvider
- FutureProvider
- StreamProvider
-
状态管理的模式:
- 依赖注入
- 状态监听
- 状态修改
-
生命周期管理:
- autoDispose
- family
- 缓存策略
这样的学习路径会让你逐步深入理解整个生态系统。每一步都建立在前一步的基础上,让学习过程更加自然。
状态库实现对比
你给出一个最小验证例子,包含每一个库的单独的使用,基本实现相同的功能的页面,这样我就能更好的理解了
我来帮你创建一个简单的计数器页面,用不同的库来实现,这样你就能看到它们的区别。
-
使用纯
riverpod
:// main.dart import 'package:flutter/material.dart'; import 'package:riverpod/riverpod.dart'; // 定义 provider final counterProvider = StateNotifierProvider<Counter, int>((ref) => Counter()); class Counter extends StateNotifier<int> { Counter() : super(0); void increment() => state++; } void main() { runApp( ProviderScope( child: MyApp(), ), ); } class CounterPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Riverpod Counter')), body: Center( child: Consumer( builder: (context, ref, child) { final count = ref.watch(counterProvider); return Text('Count: $count'); }, ), ), floatingActionButton: Consumer( builder: (context, ref, child) { return FloatingActionButton( onPressed: () => ref.read(counterProvider.notifier).increment(), child: Icon(Icons.add), ); }, ), ); } }
-
使用
flutter_riverpod
:// main.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; final counterProvider = StateNotifierProvider<Counter, int>((ref) => Counter()); class Counter extends StateNotifier<int> { Counter() : super(0); void increment() => state++; } void main() { runApp( ProviderScope( child: MyApp(), ), ); } class CounterPage extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(counterProvider); return Scaffold( appBar: AppBar(title: Text('Flutter Riverpod Counter')), body: Center( child: Text('Count: $count'), ), floatingActionButton: FloatingActionButton( onPressed: () => ref.read(counterProvider.notifier).increment(), child: Icon(Icons.add), ), ); } }
-
使用
riverpod_annotation
:// counter_provider.dart import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'counter_provider.g.dart'; class Counter extends _$Counter { int build() => 0; void increment() => state++; } // main.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'counter_provider.dart'; void main() { runApp( ProviderScope( child: MyApp(), ), ); } class CounterPage extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(counterProvider); return Scaffold( appBar: AppBar(title: Text('Riverpod Annotation Counter')), body: Center( child: Text('Count: $count'), ), floatingActionButton: FloatingActionButton( onPressed: () => ref.read(counterProvider.notifier).increment(), child: Icon(Icons.add), ), ); } }
-
使用
flutter_hooks
:// main.dart import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; void main() { runApp(MyApp()); } class CounterPage extends HookWidget { Widget build(BuildContext context) { final counter = useState(0); return Scaffold( appBar: AppBar(title: Text('Flutter Hooks Counter')), body: Center( child: Text('Count: ${counter.value}'), ), floatingActionButton: FloatingActionButton( onPressed: () => counter.value++, child: Icon(Icons.add), ), ); } }
-
使用
hooks_riverpod
:// counter_provider.dart import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'counter_provider.g.dart'; class Counter extends _$Counter { int build() => 0; void increment() => state++; } // main.dart import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'counter_provider.dart'; void main() { runApp( ProviderScope( child: MyApp(), ), ); } class CounterPage extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { // 使用 hooks 来管理本地状态 final isEnabled = useState(true); // 使用 riverpod 来管理全局状态 final count = ref.watch(counterProvider); return Scaffold( appBar: AppBar(title: Text('Hooks Riverpod Counter')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Count: $count'), Switch( value: isEnabled.value, onChanged: (value) => isEnabled.value = value, ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: isEnabled.value ? () => ref.read(counterProvider.notifier).increment() : null, child: Icon(Icons.add), ), ); } }
-
使用
provider
// 1. Provider Version // main.dart import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; // 定义数据模型 class CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } } void main() { runApp( ChangeNotifierProvider( create: (context) => CounterModel(), child: MyApp(), ), ); } class CounterPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Provider Counter')), body: Center( child: Consumer<CounterModel>( builder: (context, counter, child) { return Text('Count: ${counter.count}'); }, ), ), floatingActionButton: Consumer<CounterModel>( builder: (context, counter, child) { return FloatingActionButton( onPressed: () => counter.increment(), child: Icon(Icons.add), ); }, ), ); } }
-
使用
pure flutter
// 2. Pure Flutter Version (StatefulWidget) // main.dart import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class CounterPage extends StatefulWidget { _CounterPageState createState() => _CounterPageState(); } class _CounterPageState extends State<CounterPage> { int _count = 0; void _increment() { setState(() { _count++; }); } Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Pure Flutter Counter')), body: Center( child: Text('Count: $_count'), ), floatingActionButton: FloatingActionButton( onPressed: _increment, child: Icon(Icons.add), ), ); } }
主要区别:
riverpod
: 需要使用 Consumer 包装需要访问状态的 Widgetflutter_riverpod
: 提供了 ConsumerWidget 简化代码riverpod_annotation
: 使用代码生成简化 provider 的创建flutter_hooks
: 用于管理本地状态,提供了很多内置的 hookshooks_riverpod
: 结合了 hooks 和 riverpod 的优点
要运行这些例子,需要在 pubspec.yaml 中添加对应的依赖:
dependencies:
flutter:
sdk: flutter
riverpod: ^2.5.1
flutter_riverpod: ^2.5.1
riverpod_annotation: ^2.3.0
flutter_hooks: ^0.20.5
hooks_riverpod: ^2.5.1
dev_dependencies:
build_runner: ^2.4.8
riverpod_generator: ^2.3.5
每个实现都完成了相同的基本功能,但使用了不同的方式。从中你可以看到代码的演进和简化过程。