Flutter 状态路径一次性描述

看来新的项目有用到之前没用过的库,所以需要了解一下。

各个状态库描述

riverpod,riverpod-annotation,flutter hook,hooks-riverpod 这些有没有类似递进的关系,这样的话,我好一步一步了解,你也可以补充我漏掉的环节

让我帮你梳理这些库的递进关系和学习路径:

  1. riverpod (基础库)

    • 这是最基础的库,提供了核心的状态管理功能
    • 主要概念:Provider, StateNotifier, ProviderContainer
    // 基础写法
    final counterProvider = StateNotifierProvider<Counter, int>((ref) {
      return Counter();
    });
    
    class Counter extends StateNotifier<int> {
      Counter() : super(0);
      void increment() => state++;
    }
  2. 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');
      }
    }
  3. riverpod_annotation (简化语法)

    • 通过代码生成简化 Provider 的创建
    • 引入了 @riverpod 注解
    
    class Counter extends _$Counter {
      
      int build() => 0;
      void increment() => state++;
    }
  4. flutter_hooks (状态逻辑复用)

    • 提供了一种新的状态管理方式
    • 主要用于复用状态逻辑
    class Example extends HookWidget {
      
      Widget build(BuildContext context) {
        final controller = useTextEditingController();
        return TextField(controller: controller);
      }
    }
  5. hooks_riverpod (完整集成)

    • 结合了 flutter_riverpodflutter_hooks
    • 提供了 HookConsumerWidget 等组件
    class Example extends HookConsumerWidget {
      
      Widget build(BuildContext context, WidgetRef ref) {
        final controller = useTextEditingController();
        final count = ref.watch(counterProvider);
        return TextField(controller: controller);
      }
    }

学习建议:

  1. 先学习 riverpod 的核心概念
  2. 了解 flutter_riverpod 如何与 Flutter 集成
  3. 学习使用 riverpod_annotation 简化代码
  4. 如果需要处理复杂状态逻辑,学习 flutter_hooks
  5. 最后掌握 hooks_riverpod 的完整功能

补充一些重要的中间环节:

  1. Provider 的不同类型:

    • Provider
    • StateProvider
    • StateNotifierProvider
    • FutureProvider
    • StreamProvider
  2. 状态管理的模式:

    • 依赖注入
    • 状态监听
    • 状态修改
  3. 生命周期管理:

    • autoDispose
    • family
    • 缓存策略

这样的学习路径会让你逐步深入理解整个生态系统。每一步都建立在前一步的基础上,让学习过程更加自然。

状态库实现对比

你给出一个最小验证例子,包含每一个库的单独的使用,基本实现相同的功能的页面,这样我就能更好的理解了

我来帮你创建一个简单的计数器页面,用不同的库来实现,这样你就能看到它们的区别。

  1. 使用纯 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),
            );
            },
        ),
        );
    }
    }
  2. 使用 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),
        ),
        );
    }
    }
  3. 使用 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),
        ),
        );
    }
    }
  4. 使用 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),
        ),
        );
    }
    }
  5. 使用 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),
        ),
        );
    }
    }
  6. 使用 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),
            );
            },
        ),
        );
    }
    }
  7. 使用 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),
        ),
        );
    }
    }

主要区别:

  1. riverpod: 需要使用 Consumer 包装需要访问状态的 Widget
  2. flutter_riverpod: 提供了 ConsumerWidget 简化代码
  3. riverpod_annotation: 使用代码生成简化 provider 的创建
  4. flutter_hooks: 用于管理本地状态,提供了很多内置的 hooks
  5. hooks_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

每个实现都完成了相同的基本功能,但使用了不同的方式。从中你可以看到代码的演进和简化过程。