[英]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.正如您所说,是的, WidgetRef
和Ref
是两种不同的类型,因此是错误。
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.