likes
comments
collection
share

Flutter 状态管理的最佳组合:Riverpod + Hooks

作者站长头像
站长
· 阅读数 9

1. Flutter Hooks 的简单性

每个 Flutter 开发人员都是从使用 StatefulWidget 开始的,而我们必须通过它的基础。但想象一下,你必须创建一个大型项目,“StatefulWidget”的重用变得痛苦。这就是 flutter hooks 的由来,flutter hooks 通过创建 hooks 帮助 flutter 开发人员重用代码,然后,我们可以快速推进项目,这里有一些示例。

Flutter 状态管理的最佳组合:Riverpod + Hooks

这个类,我们都为“StatefulWidget”创建,但大多数时候,我们从不使用它,通过 flutter hooks,一个小部件的所有状态都在一个类中处理,其性能与“StatefulWidget”相同。

Flutter 状态管理的最佳组合:Riverpod + Hooks

在许多控制器的 StatefulWidget 中,例如 AnimationControllerTextEditingController, 我们需要处理所有生命周期方法:initialization, dispose, didUpdateWidget, 甚至在 State 类中添加 TickerProviderStateMixin,以及在每个需要使用这些控制器的 StatefulWidget 中添加该 mixin。

在 flutter hooks 中,我们只需要创建一个处理控制器生命周期的钩子,然后我们将在每个 HookWidget 中重用相同的钩子。

StatefulWidget 中的动画控制器

Flutter 状态管理的最佳组合:Riverpod + Hooks

HookWidget 中的动画控制器

Flutter 状态管理的最佳组合:Riverpod + Hooks

现在,我们知道使用 flutter hooks 进行编码是多么容易,以及它对于特别大的项目有何用处。我不会在创建少于 10 个小部件的应用程序中使用它,但在需要创建更多小部件的应用程序中,我不会错过使用 flutter hooks。

2. Hooks Riverpod

状态管理的简单重要性是在所有应用程序或多个小部件之间共享一个或多个变量,并且每个变量更改都必须触发正在侦听该变量的小部件中的重建。

如果您尝试仅创建一个全局变量并更改它,则不会触发小部件中的重建。为了解决这个问题,Riverpod 提供了创建一个全局提供程序的可能性,该提供程序主要携带变量,但该提供程序可以携带stream, future, ChangeNotifier,…

可以在应用程序的每个小部件中轻松访问提供者,我们只需将MyApp()小部件包装到ProviderScrope中。

Flutter 状态管理的最佳组合:Riverpod + Hooks

在新版本的 hooks_riverpod 中,有一个名为 HookConsumerWidget 的新小部件,我们必须在项目小部件中扩展它。 HookConsumerWidget 在构建中附带了其他参数,即 WidgetRef(注意 ref 很短),ref 使我们能够读取和观察提供者。

  • 读取provider:一次性读取值,值变化时不触发重建。

  • 监视provider:每次更改都会触发小部件或正在侦听 provider 的小部件部分的重建。

    Flutter 状态管理的最佳组合:Riverpod + Hooks

  • 在应用程序中观看相同的 firebase stream

    Flutter 状态管理的最佳组合:Riverpod + Hooks

正如我们可以在所有应用程序中查看 provider 一样,我们也可以更改 provider

Flutter 状态管理的最佳组合:Riverpod + Hooks

设置flutter_hooks和hooks_riverpod就是这么简单。还有复杂的概念和多种方法来完成同一件事,但应用程序中的大多数状态管理,您可能只会使用这些概念。

3. 一个示例

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

void main() {
  runApp(
    /// [MyApp] is wrapped in a [ProviderScope].
    /// This widget is where the state of most of our providers will be stored.
    /// This replaces `MultiProvider` if you've used `provider` before.
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

/// A provider that creates and listen to a [StateNotifier].
///
/// Providers are declared as global variables.
/// This does not hinder testability, as the state of a provider is instead
/// stored inside a [ProviderScope].
final counterProvider = StateNotifierProvider<Counter, int>((_) => Counter());

/// A simple [StateNotifier] that implements a counter.
///
/// It doesn't have to be a [StateNotifier], and could be anything else such as:
/// - [ChangeNotifier], with [ChangeNotifierProvider]
/// - [Stream], with [StreamProvider]
/// ...
class Counter extends StateNotifier<int> {
  Counter() : super(0);

  void increment() => state++;
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends HookConsumerWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Riverpod counter example'),
      ),
      body: Center(
        // HookConsumer is a builder widget that allows you to read providers and utilise hooks.
        child: HookConsumer(
          builder: (context, ref, _) {
            final count = ref.watch(counterProvider);

            return Text(
              '$count',
              style: Theme.of(context).textTheme.headlineMedium,
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).increment(),
        child: const Icon(Icons.add),
      ),
    );
  }
}

两个开源flutter_hooks的示例:

github.com/zsakvo/wenk…

github.com/Notsfsssf/p…

Riverpod: riverpod.dev/docs/gettin…

hooks_riverpod:pub.dev/packages/ho…

原文:omasuaku.medium.com/riverpod-fl…