【问题标题】:Flutter: how to listen to GoRouter's route / location changes in a Riverpod provider?Flutter:如何在 Riverpod 提供者中监听 GoRouter 的路线/位置变化?
【发布时间】:2022-11-02 19:50:34
【问题描述】:

我正在开发一个带有 go_router 和 riverpod 的 Flutter 应用程序,分别用于导航和状态管理。该应用程序有一个小部件,它显示实时摄像头供稿,我想“关闭它”并在其他页面堆叠在它上面时释放摄像头。

这是 GoRouter 代码的示例没有这样的逻辑。

GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => CameraWidget(),
      routes: [
        GoRoute(
          path: 'page1',
          builder: (context, state) => Page1Screen(),
        ),
      ],
    ),
  ],
)

我的第一次尝试是在 GoRoute 构建器中添加一些逻辑:

GoRouter(
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) {
        if (state.location == "/") {
          return CameraWidget();
        }
        return Center(child: Text("Camera not visible");
      },
      routes: [
        GoRoute(
          path: 'page1',
          builder: (context, state) => Page1Screen(),
        ),
      ],
    ),
  ],
)

但这显然不工作因为从“/”到“/page1”时不会再次调用构建器。

然后我想到了使用 Riverpod StateProvider 来保持相机“开/关”状态,由 GoRouter 操作。这是我尝试过的:

GoRouter(
  routes: [
    GoRoute(
      path: '/',
      redirect: (context, state) {
        final cameraStateNotifier = ref.read(cameraStateNotifierProvider.notifier);
        if (state.location == "/") {
          cameraStateNotifier.state = true;
        } else {
          cameraStateNotifier.state = false;
        }
        return null;
      },
      builder: (context, state) => CameraWidget(),
      routes: [
        GoRoute(
          path: 'page1',
          builder: (context, state) => Page1Screen(),
        ),
      ],
    ),
  ],
)

但这也不工作显然redirect 在重建小部件树时被调用,并且在这种情况下禁止更改提供者状态。

有没有人遇到过同样的问题?如何让提供商监听 GoRouter 的位置变化?

【问题讨论】:

    标签: flutter riverpod flutter-riverpod gorouter routemaster


    【解决方案1】:

    编辑:这种方法似乎不适用于Navigator.pop() 呼叫和后退按钮按下。查看当前接受的答案以获得更好的解决方案。


    我相信我找到了这样做的好方法。我首先为 GoRouter 定义了一个提供程序,然后是第二个用于收听router.routeInformationProvider 的提供程序。这是一个 ChangeNotifier,它会在每次路由信息更改时发出通知。最后,我们可以通过特定位置的第三个提供商来收听这个。

    我认为这是一个很好的解决方法,即使需要从 GoRouter 包中导入src/information_provider.dart,这并不意味着。

    import 'package:flutter_riverpod/flutter_riverpod.dart';
    import 'package:go_router/go_router.dart';
    import 'package:go_router/src/information_provider.dart';
    
    final routerProvider = Provider<GoRouter>((ref) => GoRouter(
      routes: [
        GoRoute(
          path: '/',
          builder: (context, state) => CameraWidget(),
          routes: [
            GoRoute(
              path: 'page1',
              builder: (context, state) => Page1Screen(),
            ),
          ],
        ),
      ],
    ));
    
    final routeInformationProvider = ChangeNotifierProvider<GoRouteInformationProvider>((ref) {
      final router = ref.watch(routerProvider);
      return router.routeInformationProvider;
    });
    
    final currentRouteProvider = Provider((ref) {
      return ref.watch(routeInformationProvider).value.location;
    });
    

    【讨论】:

      【解决方案2】:

      在进一步测试我的previous answer 后,我发现我使用 go_router 的方法不适用于Navigator.pop() 呼叫或后退按钮按下。在深入挖掘 go_router 的代码之后,我认为切换到 Routemaster 包会更容易,它似乎与 Riverpod 更好地集成。到目前为止,我对这种变化感到非常满意。

      这是代码:

      import 'package:flutter_riverpod/flutter_riverpod.dart';
      import 'package:routemaster/routemaster.dart';
      
      final routeMapProvider = Provider((ref) => RouteMap(routes: {
        '/': (_) => MaterialPage(child: CameraWidget()),
        '/page1': (_) => MaterialPage(child: Page1Screen()),
      }));
      
      final routerProvider = Provider((ref) {
        final routes = ref.watch(routeMapProvider);
        return RoutemasterDelegate(routesBuilder: (context) => routes);
      });
      
      final routerChangeNotifierProvider = ChangeNotifierProvider((ref) => ref.watch(routerProvider));
      
      final locationProvider = Provider((ref) => ref.watch(routerChangeNotifierProvider).currentConfiguration?.path);
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-09-19
        • 2022-11-11
        • 1970-01-01
        • 1970-01-01
        • 2020-11-06
        • 2022-06-24
        • 1970-01-01
        相关资源
        最近更新 更多