带object参数的Flutter go_router重定向

ovfsdjhp  于 2023-11-21  发布在  Flutter
关注(0)|答案(2)|浏览(151)

通常情况下,我可以将go()传递给一个路由,并指定extra来传递一个对象:void go(String location, {Object? extra})。我如何从GoRoute的redirect传递extra参数?

GoRoute(
        path: '/',
        redirect: (context, state) async {
          final theObject = tryToGetTheObject();
          if (theObject != null) {
            // context.go("/location", extra: theObject); -> throws error
            // return state.namedLocation("Location", extra: theObject); -> doesn't exist
            return state.namedLocation("Location"); // doesn't allow extra
          }
          return null;
        },
      ),

字符串
或者,我如何在构建器中加载对象,因为(页面)构建器可能不是可重定向的(即使允许重定向):

GoRoute(
        path: '/',
        redirect: (context, state) async {
          final theObject = tryToGetTheObject();
          if (theObject != null) {
            return state.namedLocation("Location");
          }
          return null;
        },
      ),
      GoRoute(
        name: 'Location',
        path: '/location',
        builder: (context, state) async { // async not allowed
          final theObject = state.extra ?? await tryToGetTheObject(); // async not allowed
          if (theObject == null) throw Exception("Invalid state");
          return LocationWidget(theObject);
        },
      ),

xqk2d5yq

xqk2d5yq1#

目前还没有正式的方法来改变GoRouterState的重定向,我相信没有很好的理由来实现这样的东西。
你的路由代码应该尽可能的简单,最多解析一些路径参数(必需的)和查询参数(可选的),然后传递给小部件。理想的情况下,这些参数只是对象的ID,这些ID将在以后由小部件的控制器/视图模型等解析。
在本例中,您使用的是可选的extra对象。
至于查询参数,我认为最好的做法是将null传递给小部件,让它负责 * 解析 * 默认值。
假设LocationWidget是一个StatefulWidget.
由于加载 object 的函数是async,因此应将结果存储为Future<T>,并使用FutureBuilder来呈现依赖于 object 的小部件:

class LocationWidget extends StatefulWidget {
  final LocationObject? object;

  const LocationWidget({
    super.key,
    this.object,
  });

  @override
  State<LocationWidget> createState() => _LocationWidgetState();
}

class _LocationWidgetState extends State<LocationWidget> {
  late Future<LocationObject?> _objectFuture;

  @override
  void initState() {
    super.initState();
    _objectFuture = widget.object != null ? Future.value(widget.object!) : _tryToGetObject();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<LocationObject?>(
      future: _objectFuture,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          final object = snapshot.data;
          return Text('Object: $object');
        } else if (snapshot.hasError) {
          final error = snapshot.error;
          return Text('Error: $error');
        } else {
          return CircularProgressIndicator();
        }
      },
    );
  }

  Future<LocationObject?> _tryToGetObject() async {
    // TODO: implement
  }
}

字符串

dy1byipe

dy1byipe2#

这是一个简单的解决方法,如果你真的需要子路由中的extra属性。你可以通过在外部创建一个额外的变量,然后在需要的时候从重定向中为它赋值。这样,每次你转到一个新的路由时,你的变量都会被覆盖。你可以访问子路由器中的变量来获取额外的变量。示例:

class AppRouter {
  // Your extra variable
  Map<String, dynamic>? _extra;
  
  AppRouter({required this.auth});
  Auth auth;
  
  late GoRouter router = GoRouter(
    refreshListenable: auth,
    redirect: (context, state) {

      // considering the extra is a map
      _extra = state.extra as Map<String, dynamic>?;
      if (auth.isLoggedIn == false) {
        return Login.route;
      }

      if (state.location == "/second-page") {
        return SecondPage.route;
      }

      return Home.route;
    },
    routes: [
      GoRoute(
        path: Login.route,
        name: 'login',
        builder: (context, state) {
          return const Login();
        },
      ),
      GoRoute(
        path: Home.route,
        name: 'Home_page',
        builder: (context, state) {

          // _extra is accessible here
          return Home(myKey: _extra);
        },
      ),
      GoRoute(
        path: SecondPage.route,
        name: 'second_page',
        builder: (context, state) {
          return const SecondPage();
        },
      ),
    ],
    initialLocation: Home.route,
  );
}

字符串

相关问题