How to handle deeplinking in Flutter using routes
1,500
If what you needed is to be able to navigate without getting the context from Navigtor.of
as you want to handling deeplink, you need to use navigatorKey
property, you can read the details here.
then your code will be look like this
void main() { ... }
class MyApp extends StatefulWidget { ... }
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
Uri _latestUri;
Object _err;
GlobalKey<NavigatorState> navigatorKey = GlobalKey();
StreamSubscription _sub;
@override void initState() { ... }
@override void dispose() { ... }
void _handleIncomingLinks() {
_sub = uriLinkStream.listen((Uri uri) {
if (!mounted) return;
print('got uri: $uri'); // printed: got uri: myapp://?key1=test
setState(() {
_latestUri = uri;
_err = null;
});
// use the navigatorkey currentstate to navigate to the page you are intended to visit
navigatorKey.currentState.pushNamedAndRemoveUntil('login', (route) => false);
}, onError: (Object err) { ... });
@override Widget build(BuildContext context) { ... }
}
Author by
Rutger Huijsmans
Updated on December 30, 2022Comments
-
Rutger Huijsmans over 1 year
I'm attempting to build deeplink functionality and so far the initial start of the app and retrieving parameters from the deeplink is going fine.
However I am having issues navigating to a screen after I deeplink into the app. How should I do this?
My code looks like this:
void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin { Uri _latestUri; Object _err; StreamSubscription _sub; @override void initState() { super.initState(); _handleIncomingLinks(); } @override void dispose() { _sub?.cancel(); super.dispose(); } void _handleIncomingLinks() { _sub = uriLinkStream.listen((Uri uri) { if (!mounted) return; print('got uri: $uri'); // printed: got uri: myapp://?key1=test setState(() { _latestUri = uri; _err = null; Navigator.pushNamed(context, 'login'); // This doesn't work because the context does not include navigator }); }, onError: (Object err) { if (!mounted) return; print('got err: $err'); setState(() { _latestUri = null; if (err is FormatException) { _err = err; } else { _err = null; } }); }); } @override Widget build(BuildContext context) { return MaterialApp( initialRoute: 'splash-screen', onGenerateRoute: (settings) { switch (settings.name) { case 'splash-screen': return PageTransition( child: BlocProvider( create: (context) => SplashScreenCubit(APIRepository( apiClient: APIClient(httpClient: http.Client()))), child: SplashScreen(), ), type: PageTransitionType.rightToLeft, settings: settings); break; case 'create-account': return PageTransition( child: BlocProvider( create: (context) => CreateAccountScreenCubit( APIRepository( apiClient: APIClient(httpClient: http.Client()))), child: CreateAccountScreen(), ), type: PageTransitionType.rightToLeft, settings: settings); break; case 'login': return PageTransition( child: BlocProvider( create: (context) => LoginScreenCubit(APIRepository( apiClient: APIClient(httpClient: http.Client()))), child: LoginScreen(), ), type: PageTransitionType.rightToLeft, settings: settings); break; default: return null; }, ); } }