简体   繁体   English

flutter_riverpod - 在 `context` 可用时访问 `Ref`

[英]flutter_riverpod - Accessing a `Ref` when `context` is available

I'm in the process of migrating my app to use flutter_riverpod package. At the moment, my app is using provider package to manage/deal with app state.我正在迁移我的应用程序以使用flutter_riverpod package。目前,我的应用程序正在使用provider package 来管理/处理应用程序 state。

I have a lot of static methods inside multiple utility classes that take a BuildContext as input.我在多个实用程序类中有很多 static 方法,这些方法将BuildContext作为输入。 I use the context to access the provider, which allows me to read and modify the state:我使用上下文来访问提供程序,它允许我读取和修改 state:

// This relies on the provider package
abstract class SomeRandomUtilityClass {

  static FutureOr<String?> redirect(BuildContext context) {
    bool isSignedIn = context.read<AuthProvider>().isSignedIn;
  
    if (!isSignedIn) {
      return '/signIn';
    } else {
      return null;
    }
  }

How do I achieve this with Riverpod?我如何使用 Riverpod 实现这一目标? From what I understand, you need a Ref to be able to read/write from/to a provider, but I'm not even sure if the APIs allow it.据我了解,您需要一个Ref才能从提供者读取/写入提供者,但我什至不确定 API 是否允许这样做。

I tried replacing the BuildContext parameters of my methods with a Ref object, but I'm having trouble getting one.我尝试用Ref object 替换我的方法的BuildContext参数,但我无法获得一个。 All I can access is a WidgetRef :我只能访问WidgetRef

class App extends ConsumerWidget {
  /** ... **/

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return MaterialApp.router(
      /** ... **/
      routerConfig: GoRouter(
        /** ... **/
        routes: [
          GoRoute(
            /** ... **/
            // This doesn't work, because the method I'm calling expects a Ref,
            // and not a WidgetRef.
            redirect: (_, __) => SomeRandomUtilityClass.redirect(ref),
          ),
        ],
      ),
    );
  }
}

An easy fix would be to modify my static methods by changing the type of the parameter from Ref to WidgetRef , but the maintainer of the Riverpod package says that passing WidgetRef s is a bad idea .一个简单的修复方法是通过将参数类型从Ref更改为WidgetRef来修改我的 static 方法,但是 Riverpod package 的维护者说传递WidgetRef是个坏主意

I might be misunderstanding something.我可能误会了什么。 Please let me know if I am.如果我是,请告诉我。

As you stated, yes, WidgetRef and Ref are of two different types, thus the error.正如您所说,是的, WidgetRefRef是两种不同的类型,因此是错误。

To understand why, consider that this: passing WidgetRef is a bad idea because WidgetRef s are (indeed) linked their Widget 's element .要理解原因,请考虑以下几点:传递WidgetRef是一个坏主意,因为WidgetRef是(确实)链接了它们的Widget元素 Their life cycle are indeed tied to the life cycle of a widget, whereas the lifecycle of a provider is a different thing.它们的生命周期确实与小部件的生命周期相关,而提供者的生命周期是另一回事。 In a certain way, WidgetRef is closer to an AutoDisposeRef .在某种程度上, WidgetRef更接近AutoDisposeRef

But passing around WidgetRef s around would be dangerous since you could technically mark widgets as dirty in a way that's not meant to be with Riverpod.但是四处传递WidgetRef是很危险的,因为从技术上讲,您可以以一种不适用于 Riverpod 的方式将小部件标记为脏的。

Long story short, in general , there's a good chance you want to refactor static methods into a single simple provider, which is, in the end, just a function with a ref wrapper on it.长话短说,一般来说,您很有可能希望将 static 方法重构为一个简单的提供程序,最终,它只是一个带有ref包装器的 function。

I'd highly suggest using riverpod_annotation , too.我也强烈建议使用riverpod_annotation You'd save time and you'd obtain something very readable and concise (and hassle-free):你会节省时间你会得到一些非常可读和简洁(而且无忧无虑)的东西:

@riverpod
T yourFunction(YourFunctionRef ref) {
  final someValue = ref.watch(someDependencyProvider);

  // logic

  return someComputedValue; // Type T
}

In your specific use case, though, you're trying to implement a redirect with go router and riverpod.但是,在您的特定用例中,您正在尝试使用 go 路由器和 riverpod 实现重定向。 I'd avoid creating a simple provider like that, since it would cause the root of your app to rebuild on auth change.我会避免创建这样一个简单的提供程序,因为它会导致您的应用程序的根目录在身份验证更改时重建。

That's a "deep" topic, and there are several way to do so;这是一个“深奥”的话题,有几种方法可以做到; I've created a repo here just to show off how to work around this.我在这里创建了一个回购只是为了展示如何解决这个问题。 It's a 3rd party riverpod examples repo.这是第 3 方 riverpod 示例回购。

Check the complete_example folder, there for a full example, or search for older and simpler examples in other folders.检查complete_example文件夹,那里有一个完整的例子,或者在其他文件夹中搜索更老更简单的例子。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 flutter_riverpod 更新 StateProvider - update StateProvider with flutter_riverpod flutter_riverpod 如何监听列表 - How flutter_riverpod listens to a list 当通知程序尝试在flutter_riverpod中更新其state错误时抛出异常 - Threw an exception when the notifier tried to update its state error in flutter_riverpod 为什么初始化期间flutter_riverpod出现state更改错误 - Why state change error occurs on flutter_riverpod during initialization Flutter_riverpod 安装时出现问题 - Flutter_riverpod giving me problems while installing URI 的目标不存在:&#39;package:flutter_riverpod/flutter_riverpod.dart&#39; - Target of URI doesn't exist: 'package:flutter_riverpod/flutter_riverpod.dart' ref.listen 在 Riverpod flutter 中 - ref.listen in Riverpod flutter Flutter中的flutter_riverpod如何更方便的将ConsumerWidget转换为ConsumerStatefulWidget? - How does flutter_riverpod in Flutter convert ConsumerWidget to ConsumerStatefulWidget more conveniently? flutter_riverpod 1.0.0 阻止应用程序在调试模式下在 Chrome 中运行 - flutter_riverpod 1.0.0 prevents app from running in Chrome in debug mode 如何在 TextFormFields 上使用 Flutter_Riverpod 和 TextEditingControllers 避免 markNeedsBuilder() 错误? - How do avoid markNeedsBuilder() error using Flutter_Riverpod and TextEditingControllers on TextFormFields?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM