用户输入 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,但是达到了目的。
我的应用程序使用带有 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,但是达到了目的。