Flutter状态管理插件jaspr_riverpod的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter状态管理插件jaspr_riverpod的使用

简介

jaspr_riverpod 是一个为 Jaspr 框架设计的状态管理库,它基于 Riverpod 2,并支持所有类型的提供者(Provider)和修饰符。与 flutter_riverpod 相比,jaspr_riverpod 有一些不同的特性,主要是去除了 ConsumerConsumerComponent,并引入了 SyncProvider 用于在服务器和客户端之间同步状态。

主要差异

  1. 没有 Consumer / ConsumerComponent:你可以直接使用 context.read()context.watch() 来访问提供者。
  2. 新增 SyncProvider:用于在服务器和客户端之间同步值,特别适用于服务器端渲染(SSR)。

访问提供者

jaspr_riverpod 提供了对 BuildContext 的扩展方法,使得你可以直接在任何组件中使用 context.watch()context.read() 来访问提供者,而不需要像 flutter_riverpod 那样依赖 WidgetRef

示例代码(Flutter vs Jaspr)

Flutter
// (Flutter)
// 需要继承自 ConsumerWidget
class MyWidget extends ConsumerWidget {
  // 需要接受 WidgetRef 参数
  Widget build(BuildContext context, WidgetRef ref) {
    // 使用 ref 来访问提供者
    var value = ref.watch(myProvider);
    return Text(value);
  }
}
Jaspr
// (Jaspr)
// 只需继承普通的组件
class MyComponent extends StatelessComponent {
  // 不需要额外的参数
  Iterable<Component> build(BuildContext context) sync* {
    // 使用 context 来访问提供者
    var value = context.watch(myProvider);
    yield Text(value);
  }
}

替代 Consumer

jaspr_riverpod 中,我们不再需要 Consumer 组件。如果你只想让组件树的某一部分在监听提供者时重新构建,可以使用 Builder 组件。Builder 会提供一个新的 context,你可以在其中调用 context.watch()

示例代码

Builder(
  builder: (context) sync* {
    var value = context.watch(...);
    yield ...;
  },
);

预加载和同步提供者状态

jaspr_riverpod 提供了 SyncProvider,用于在服务器和客户端之间同步状态。SyncProvider 的创建函数只会在服务器端执行,客户端会接收到同步后的值。这在服务器端渲染(SSR)场景中非常有用。

示例代码

final mySyncProvider = SyncProvider<int>((ref) async {
  // 在服务器端执行异步操作,例如从数据库获取数据
  await Future.delayed(Duration(seconds: 1));
  return 100;
}, id: 'initial_count');
  • id 是必需的,用于标识同步的值。
  • create 函数只在服务器端执行,客户端不会执行该函数,而是接收同步后的值。
  • SyncProvider 类似于 FutureProvider,返回一个 AsyncValue<T> 类型的值。

完整示例 Demo

以下是一个完整的 jaspr_riverpod 示例,展示了如何使用 ProviderSyncProvider 来管理状态。

1. 创建 Provider

首先,我们定义一个简单的 StateProvider 来管理计数器的状态。

import 'package:jaspr/jaspr.dart';
import 'package:jaspr_riverpod/jaspr_riverpod.dart';

// 定义一个 StateProvider 来管理计数器
final counterProvider = StateProvider<int>((ref) => 0);

// 定义一个 SyncProvider 来模拟从服务器获取初始计数
final initialCounterProvider = SyncProvider<int>((ref) async {
  // 模拟从服务器获取数据
  await Future.delayed(Duration(seconds: 1));
  return 100;
}, id: 'initial_counter');

2. 创建组件

接下来,我们创建一个组件来显示计数器,并允许用户通过按钮增加计数。

class CounterApp extends StatelessComponent {
  @override
  Iterable<Component> build(BuildContext context) sync* {
    // 使用 context.watch 来监听计数器的状态
    final counter = context.watch(counterProvider);
    final initialCounter = context.watch(initialCounterProvider);

    yield Div(
      children: [
        Text('当前计数: ${counter.state}'),
        Button(
          child: Text('增加计数'),
          onClick: () {
            // 使用 context.read 来更新计数器
            context.read(counterProvider).state++;
          },
        ),
        if (initialCounter.value is AsyncData<int>)
          Text('初始计数: ${initialCounter.value.asData!.value}'),
        else if (initialCounter.value is AsyncLoading)
          Text('正在加载初始计数...'),
        else if (initialCounter.value is AsyncError)
          Text('加载初始计数失败: ${initialCounter.value.error}'),
      ],
    );
  }
}

3. 运行应用

最后,我们将 CounterApp 组件作为应用程序的根组件运行。

void main() {
  runApp(
    ProviderScope(
      child: CounterApp(),
    ),
  );
}

更多关于Flutter状态管理插件jaspr_riverpod的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter状态管理插件jaspr_riverpod的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter中的状态管理插件jaspr_riverpod(通常简称为riverpod),这里有一个基本的示例代码来展示如何使用它。riverpod是一个强大的状态管理库,它基于provider包但提供了更多的功能和更简洁的API。

首先,确保你的pubspec.yaml文件中已经添加了riverpod依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_riverpod: ^x.y.z  # 替换为最新版本号

然后,运行flutter pub get来获取依赖。

接下来,让我们创建一个简单的示例,展示如何使用riverpod来管理应用状态。

主文件 (main.dart)

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

void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Riverpod Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

创建一个简单的计数器状态管理

状态定义和管理 (counter_provider.dart)

import 'package:flutter_riverpod/flutter_riverpod.dart';

final counterProvider = StateNotifierProvider<Counter, int>((ref) {
  return Counter();
});

class Counter extends StateNotifier<int> {
  Counter() : super(0);

  void increment() {
    state++;
  }
}

用户界面 (my_home_page.dart)

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'counter_provider.dart';

class MyHomePage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final counter = ref.watch(counterProvider);
    final void Function() increment = ref.read(counterProvider.notifier).increment;

    return Scaffold(
      appBar: AppBar(
        title: Text('Riverpod Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: increment,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

解释

  1. ProviderScope:在main.dart中,我们使用ProviderScope包裹了整个应用。这是使用riverpod时必须的,因为它为所有的Provider提供了一个上下文。

  2. StateNotifierProvider:在counter_provider.dart中,我们定义了一个StateNotifierProvider,它管理一个Counter类的实例。Counter类继承自StateNotifier<int>,这意味着它持有一个int类型的状态。

  3. Counter 类Counter类有一个increment方法,用于增加状态值。

  4. ConsumerWidget:在my_home_page.dart中,MyHomePage类继承自ConsumerWidget,这使得我们可以使用ref.watchref.read方法来访问和监听Provider的状态。

  5. ref.watch:用于监听Provider的状态,并在状态变化时重新构建UI。

  6. ref.read:用于读取Provider的实例,并调用其方法,但不监听状态变化。

这个示例展示了如何使用riverpod来管理一个简单的计数器状态。你可以根据需要扩展这个示例,以管理更复杂的状态和逻辑。

回到顶部