flutter_riverpod -当' context '可用时访问' Ref '



我正在迁移我的应用程序使用flutter_riverpod包的过程中。目前,我的应用程序正在使用provider包来管理/处理应用程序状态。

我在多个实用程序类中有很多静态方法,它们将BuildContext作为输入。我使用上下文来访问提供程序,它允许我读取和修改状态:

// 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;
}
}

我如何在Riverpod中实现这一点?从我的理解,你需要一个Ref能够读/写/从一个提供者,但我甚至不确定如果api允许它。

我试着用Ref对象替换我的方法的BuildContext参数,但我很难得到一个。我能访问的只有一个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),
),
],
),
);
}
}

一个简单的修复方法是修改我的静态方法,将参数的类型从Ref更改为WidgetRef,但是Riverpod包的维护者说传递WidgetRef是一个坏主意。

我可能误解了什么。如果我是,请告诉我。

如您所述,是的,WidgetRefRef是两种不同的类型,因此错误。

要理解为什么,考虑一下:传递WidgetRef是一个坏主意,因为WidgetRefs(确实)链接了它们的Widget元素。它们的生命周期确实与小部件的生命周期联系在一起,而提供者的生命周期则是另一回事。在某种程度上,WidgetRef更接近AutoDisposeRef

但是传递WidgetRefs是很危险的,因为从技术上讲,你可以用一种不适合Riverpod的方式将widget标记为dirty。

长话短说,通常,您很有可能希望将静态方法重构为单个简单的提供者,最终,它只是一个带有ref包装器的函数。

我强烈建议也使用riverpod_annotation。你会节省时间你会得到一些非常易读和简洁的东西:

@riverpod
T yourFunction(YourFunctionRef ref) {
final someValue = ref.watch(someDependencyProvider);
// logic
return someComputedValue; // Type T
}

特定的用例中,你试图用go路由器和riverpod实现重定向。我会避免创建这样一个简单的提供商,因为它会导致你的应用程序的根重新构建auth更改。

这是一个"深度"主题,有几种方法可以做到这一点;我在这里创建了一个回购,只是为了展示如何解决这个问题。这是一个第三方的riverpod示例库。

检查complete_example文件夹,那里有一个完整的例子,在其他文件夹中搜索更老更简单的例子。

最新更新