用户输入 URL 地址时如何在 flutter 中传递参数(使用 auto_route)

How to pass in arguments in flutter when user input URL address (using auto_route)

我的应用程序使用带有 auto_router 0.6.9 包的 flutter,我希望 用户能够输入网址 http://localhost/#/book/123并能够访问 book 123 并显示 book123、他们的姓名和电子邮件(如果他们已登录)。我已经用 auto_router 找出了路由部分,但是当用户将地址直接输入浏览器时,应该传递到页面的参数为空。

我想知道有没有办法在显示页面之前解析 url 并传入所需的参数。感谢您的帮助或提示!

我的 router.dart 页面:

@MaterialAutoRouter(
  routes: <AutoRoute>[
    // some other pages...
    MaterialRoute(path: "/book/:id", page: MultiProvider),
  ],
)
class $ModularRouter {}

为多提供商参数 class 生成的 router.gr.dart 是:

/// MultiProvider arguments holder class
class MultiProviderArguments {
  final Key key;
  final List<SingleChildWidget> providers;
  final Widget child;
  final Widget Function(BuildContext, Widget) builder;
  MultiProviderArguments(
      {this.key, @required this.providers, this.child, this.builder});
}

我的图书菜单页面包含一个导航:
(这是我通常如何在另一页中调用 BookPage 的示例)

child: GestureDetector(
onTap: () => ExtendedNavigator.of(context).push(
    Routes.multiProvider(id: book[index].bookID),
    arguments: MultiProviderArguments(
    providers: [
        Provider<UserData>.value(
            value: userdata,
        ),
        Provider<List<BookInfo>>.value(
            value: book,
        ),
    ],
    child: BookPage(
        bookId: book[index].bookID,
        name: userdata.userName,
        email: userdata.email,
    ),
    ),
),
...

BookPage 接受 3 个参数 bookId、姓名和电子邮件:

class BookPage extends StatefulWidget {
  final String bookId;
  final String name;
  final String email;

  BookPage({
    this.bookId,
    this.name,
    this.email,
  });
...
}

...

class _BookPageState extends State<BookPage> {
    ...
    Widget build(BuildContext context) {
        final currentUser = Provider.of<UserData>(context, listen: false);
        final currentBook = Provider.of<List<BookInfo>>(context, listen: false);
        ...
    }
}

我想出了一个创可贴解决方案(我认为这不是永久性的):

我已经放弃使用自动路由,我不知道如何解析 url 而是使用 onGenerateRoute:

onGenerateRoute: (settings) {
  final settingsUri = Uri.parse(settings.name);
  final user = Provider.of<User>(context);

  if (user == null) {
    return MaterialPageRoute(
        builder: (context) {
          return LogInPage();
        }
    );
  } else {
    // Handle '/'
    if (settingsUri.pathSegments.length == 0) {
      return MaterialPageRoute(
          builder: (context) {
            return PageWrapper(false, bookid);
          }
      );
    }

    // Handle '/book/:id'
    if (settingsUri.pathSegments.length == 2) {
      if (settingsUri.pathSegments.first != 'book') {
        return MaterialPageRoute(
            builder: (context) {
              return UnknownPage();
            }
        );
      }

      final bookid = settingsUri.pathSegments.elementAt(1);
      if (bookid == null) {
        return MaterialPageRoute(
          builder: (context) {
            return UnknownPage();
          }
        );
      }

      return MaterialPageRoute(
          builder: (context) {
            return PageWrapper(false, bookid);
          }
      );
    }
  }
  //Handle other unknown Routes
  return MaterialPageRoute(
      builder: (context) {
        return UnknownPage();
      }
  );
}

PageWrapper认证用户,构建providers,调用BookPageclass,我把代码放在userData providers已经初始化的地方:

if (this.needRedirect == true) {
  return Scaffold(
    ...
    body: FutureBuilder(
        future: Future.wait([userData]),
        builder: (context, snapshot) {
          return MultiProvider(
              providers: [
                //initialize using streamproviders
                ...
              ],
              child: BookPage(
                bookId: book[index].bookID,
                name: userdata.userName,
                email: userdata.email,
              ),
          );
        }),
  );
}
else {...}

简短的回答是我在 onGenerateRoutes 中调用了 WrapperPage,因为提供程序未在 main.dart 中初始化,但它们在 WrapperPage 中初始化。然后我在提供程序初始化后将重定向代码放在 WrapperPage 中并调用 BookPage。

这个方法虽然引起了其他bug,但是达到了目的。