我的Flutter项目正在迁移到go_router
,我很难理解如何使用GoRoute
的build
方法或redirect
方法访问riverpod提供程序,因为我需要访问用户的数据来控制导航。
我有一个顶级重定向,用于检查用户是否登录,如果没有,则将其发送到LoginPage。所有用户都可以访问我的应用程序中所谓的活动,但只有管理员可以编辑它们。用户是否是管理员存储在riverpoduserDataProvider
中,如果用户登录,它总是包含一个用户。现在,如果用户试图进入路线/:activityId?edit=true
,我想通过访问userDataProvider
来检查他们是否被允许。然而,我看不出访问这个提供商的干净方式是什么
我在某个地方找到了(再也找不到线程了(,其中一种方法是使用ProviderScope.containerOf(context).read(userDataProvider)
,但我以前从未见过,这对我来说有点奇怪。这是一种方法吗?
我的GoRoute看起来像这样:
GoRoute(
path: RouteName.event.relPath,
builder: (context, state) {
final String? id = state.params['id'];
final bool edit = state.queryParams['edit'] == 'true';
if (state.extra == null) {
// TODO: Fetch data
}
final data = state.extra! as Pair<ActivityData, CachedNetworkImage?>;
if (edit) {
return CreateActivity(
isEdit: true,
data: data.a,
banner: data.b,
);
}
return ActivityPage(
id: id!,
data: data.a,
banner: data.b,
);
},
redirect: (context, state) {
final bool edit = state.queryParams['edit'] == 'true';
if (edit) {
// IMPORTANT: How to access the ref here?
final bool isAdmin =
ref.read(userDataProvider).currentUser.customClaims.admin;
if (isAdmin) {
return state.location; // Includes the queryParam edit
} else {
return state.subloc; // Does not include queryParam
}
} else {
return state.path;
}
},
),
在我当前的应用程序中,我使用了类似的方法:
提供商注册部分(providers.dart(:
final routerProvider = Provider<GoRouter>((ref) {
final router = RouterNotifier(ref);
return GoRouter(
debugLogDiagnostics: true,
refreshListenable: router,
redirect: (context, state) {
router._redirectLogic(state);
return null;
},
routes: ref.read(routesProvider));
});
class RouterNotifier extends ChangeNotifier {
final Ref _ref;
RouterNotifier(this._ref) {
_ref.listen<AuthState>(authNotifierProvider, (_, __) => notifyListeners());
}
String? _redirectLogic(GoRouterState state) {
final loginState = _ref.watch(authNotifierProvider);
final areWeLoggingIn = state.location == '/login';
if (loginState.state != AuthenticationState.authenticated) {
return areWeLoggingIn ? null : '/login';
}
if (areWeLoggingIn) return '/welcome';
return null;
}
}
作为路由器的主要应用程序构建(app.dart(:
class App extends ConsumerWidget {
const App({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context, WidgetRef ref) {
final GoRouter router = ref.watch(routerProvider);
return MaterialApp.router(
routeInformationProvider: router.routeInformationProvider,
routeInformationParser: router.routeInformationParser,
routerDelegate: router.routerDelegate,
debugShowCheckedModeBanner: false,
title: 'Flutter Auth',
}
}
}
作为入口点(main.dart(:
Future<void> main() async {
F.appFlavor = Flavor.dev;
WidgetsFlutterBinding.ensureInitialized();
await setup();
runApp(ProviderScope(
observers: [
Observers(),
],
child: const App(),
));
}