我正在使用Flutter Navigator 2.0与嵌套路由 - 使用
在当前使用情况下,我想使用深链接打开嵌套路由中的页面,因此我按照说明进行了配置:
1. Android清单文件中接收自定义模式和主机URL 2.
当应用程序在前台时(例如在启动屏幕上),一切正常 - 我接收到pushRoute事件,并且根和嵌套
在Android清单文件中配置Flutter
主要应用程序类(在RunApp中使用):
使用给定的类,启动应用程序时的深链接始终为空。我的最佳猜测是
MaterialApp.router()
创建一个主路由,使用Router()
小部件和适当的RouterDelegates创建子路由(在底部导航栏中用作页面)。在当前使用情况下,我想使用深链接打开嵌套路由中的页面,因此我按照说明进行了配置:
1. Android清单文件中接收自定义模式和主机URL 2.
RouteInformationParser
将其解析为我的模型
3. PlatformRouteInformationProvider
通知所有嵌套的路由器有关路由更改的信息当应用程序在前台时(例如在启动屏幕上),一切正常 - 我接收到pushRoute事件,并且根和嵌套
Router
小部件正确处理深链接。但是,当应用程序未启动时,我没有接收到设置为我的深链接的initialRoute,而是收到了默认的空RouteInformation
。为什么会这样?以下是我的代码示例:在Android清单文件中配置Flutter
MainActivity
: <activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" />
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- For deeplinking -->
<meta-data
android:name="flutter_deeplinking_enabled"
android:value="true" />
<!-- Accepts links in format myapp://*.myapp.com/ -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="*.myapp.com"
android:scheme="myapp" />
</intent-filter>
</activity>
主要应用程序类(在RunApp中使用):
class MyApp extends StatelessWidget {
static PlatformRouteInformationProvider routeInformationProvider =
PlatformRouteInformationProvider(
initialRouteInformation: const RouteInformation(),
);
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) => FutureBuilder(
future: AppInit.initApp(),
builder: (context, snapshot) {
return _app();
},
);
Widget _app() => MultiRepositoryProvider(
providers: AppRepositoryProviders().list,
child: MultiBlocProvider(
providers: AppBlocProviders().list,
child: MaterialApp.router(
supportedLocales: LocalizationConfig.supportedLocales,
localizationsDelegates: LocalizationConfig.localizationDelegates,
theme: LightTheme().themeData,
routerDelegate: UserSessionRouter(),
routeInformationParser: AppRouteInformationParser(),
routeInformationProvider: routeInformationProvider,
backButtonDispatcher: RootBackButtonDispatcher(),
),
),
);
...
}
RouteInformationParser 实现:
class AppRouteInformationParser extends RouteInformationParser<DeepLinkRoute> {
@override
Future<DeepLinkRoute> parseRouteInformation(
RouteInformation routeInformation) async {
if (routeInformation.location.isNullOrEmpty) {
return DeepLinkRoute.none();
} else {
return DeepLinkParser.parse(routeInformation.location!).fold(
(data) => DeepLinkRoute(
link: data,
route: _getRouteFromDeeplink(data),
),
(error) => DeepLinkRoute.none(),
);
}
}
RouteDefinition _getRouteFromDeeplink(DeepLink deepLink) {
switch (deepLink.path) {
case '/auth/signup':
return AppRoutes.authSignup;
default:
return AppRoutes.none;
}
}
@override
RouteInformation restoreRouteInformation(DeepLinkRoute configuration) =>
RouteInformation(
location: configuration.link.path,
state: configuration.link.queryParams,
);
}
嵌套(子)路由的屏幕:
class AuthScreen extends StatefulWidget {
const AuthScreen({Key? key}) : super(key: key);
@override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
final AuthRouter _routerDelegate = AuthRouter();
ChildBackButtonDispatcher? _backButtonDispatcher;
@override
void didChangeDependencies() {
_initBackButtonDispatcher();
super.didChangeDependencies();
}
void _initBackButtonDispatcher() {
_backButtonDispatcher ??=
ChildBackButtonDispatcher(context.router.backButtonDispatcher!);
_backButtonDispatcher?.takePriority();
}
@override
Widget build(BuildContext context) => MultiBlocProvider(
providers: [
BlocProvider(
create: (context) => SigninScreenCubit(
usersRepository: context.read<UsersRepository>(),
))
],
child: Router(
routerDelegate: _routerDelegate,
backButtonDispatcher: _backButtonDispatcher,
routeInformationParser: AppRouteInformationParser(),
routeInformationProvider:
MyApp.routeInformationProvider,
),
);
}
我使用以下命令测试深层链接:
adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "$1"
使用给定的类,启动应用程序时的深链接始终为空。我的最佳猜测是
RouteInformationProvider
实例: static PlatformRouteInformationProvider routeInformationProvider =
PlatformRouteInformationProvider(initialRouteInformation: const RouteInformation());
可能是某种配置错误,但我自己无法确定。
更新:
我已在iOS上进行了测试,令人惊讶的是,它与Android完全相反——当应用程序被杀死时,它可以正常使用深层链接打开,但当它在前台运行时,路由器(Router)
永远不会更新,且路线信息提供程序(RouteInformationProvider)
和路线信息解析器(RouteInformationParser)
都从未被调用。我在Flutter GitHub存储库中找到了一些相关问题,虽然它们已经关闭,但我认为它们并没有解决我的问题。这个问题似乎与我的问题几乎相同,但我查看了应该解决它的PR,我发现其他用户也报告了iOS上深层链接的问题。