我正在迁移我的应用以使用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
s是个坏主意。
我可能误会了什么。如果我是的话请告诉我。
1条答案
按热度按时间ffscu2ro1#
正如你所说,是的,
WidgetRef
和Ref
是两种不同的类型,因此错误。要理解其中的原因,请考虑以下情况:传递
WidgetRef
是一个坏主意 * 因为 *WidgetRef
(实际上)链接了它们的Widget
的 * 元素 。它们的生命周期实际上与小部件的生命周期相关联,而提供者的生命周期则是另一回事。在某种程度上,WidgetRef
更接近于AutoDisposeRef
。但是传递
WidgetRef
是危险的,因为从技术上讲,你可以用一种不适合Riverpod的方式将小部件标记为脏。长话短说, 一般来说 *,您很可能希望将静态方法重构为单个简单的提供者,最终,它只是一个带有
ref
Package 器的函数。我强烈建议您也使用
riverpod_annotation
,这样可以节省时间 , 并且可以获得可读性强、简洁(而且没有麻烦)的内容:在您的 * 特定 * 用例中,您尝试使用go router和riverpod实现重定向。我会避免创建这样一个简单的提供程序,因为它会导致应用的根在auth更改时重建。
那是一个“深刻”的主题,而且有几种方法可以这样做;我创建了一个repo here来演示如何解决这个问题。
检查
complete_example
文件夹,那里有一个完整的例子,* 或 * 在其他文件夹中搜索更老和更简单的例子。