
Insight

Insight

Insight
Deep linking and complex navigation in Flutter
Deep linking and complex navigation in Flutter
Sep 16, 2024




Photo by Raphaël Biscaldi on Unsplash
Deep linking and navigation are two essential aspects that significantly influence the user experience in mobile apps. Deep links enable users to be directed straight to specific content within an app, rather than just redirecting them to the homepage. This is particularly useful when content is shared via social media or marketing campaigns. Navigation, on the other hand, governs how users are guided through the app and how content is organized. A well-thought-out navigation structure ensures that users can intuitively move through the app.
In Flutter, there are various ways to implement deep links and navigation. The use of the go_router
library has recently become an extremely popular method for efficiently managing complex navigation structures. With go_router
, you can create flexible routes, support URL-based navigation, and seamlessly integrate deep links. In this article, you'll learn how to set up deep links and how go_router
helps you master even complicated navigation logics in Flutter.
Deep Links in Flutter
Deep links are URLs that lead users directly to specific areas of an app, rather than just opening the app. This greatly improves the user experience, as they are directed straight to relevant content. There are two main types of deep links:
Basic Deep Links: Redirect users to the app without ensuring that the app is installed. If the app is not installed, the link leads to a dead end.
Deferred/Universal Links: These redirect users to the app store if the app is not installed, and then lead to the originally linked content after installation.
Processing Deep Links in Flutter:
Use the Flutter
uni_links
package to process deep links in your app:
import 'package:uni_links/uni_links.dart';
void initDeepLinkListener() {
getLinksStream().listen((String? deepLink) {
// Here you can process the navigation based on the link
if (deepLink != null) {
// Handle the deep link
print("Received deep link: $deepLink");
}
});
}
Testing Deep Links:
Test your deep links by opening a URL from a browser or a messaging service. On Android, you can also use the
adb
command:
adb shell am start -W -a android.intent.action.VIEW -d "https://www.deine-domain.de/angebot" com.deineapp
go_router for Complex Navigation Structures
The go_router
library offers an elegant solution for efficiently managing complex navigation structures in Flutter apps. Unlike Flutter's standard Navigator
API, which often becomes complicated due to manual routing and tracking of routes, go_router
enables declarative and URL-based navigation. This not only simplifies handling complex routes, but it also streamlines the integration of deep links and web-like navigation patterns.
Advantages of go_router
URL-based Navigation: Just like web applications, you can control the navigation of your app through URLs, which is particularly helpful for deep links and the web component of Flutter apps.
Simple Routing: Instead of manually handling navigation with the Navigator API, you define all routes in a declarative way, which increases clarity and maintainability.
Support for Deep Links and Dynamic Routes: With
go_router
, dynamic URL segments and parameters can be easily processed, which is essential for flexible and dynamic apps.Redirects and Error Routes: You can easily implement redirects or 404 pages in your app when users access invalid links.
Example: Basic Setup of go_router
To use go_router
, you first need to add it to your project:
dependencies:
go_router: ^6.0.0 #check latest version at pub.dev
In your main.dart
, you set up the GoRouter
and define the routes:
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
void main() {
final GoRouter _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => HomeScreen(),
),
GoRoute(
path: '/details/:id',
builder: (context, state) {
final id = state.params['id'];
return DetailsScreen(id: id);
},
),
],
errorBuilder: (context, state) => ErrorScreen(),
);
runApp(MyApp(router: _router));
}
class MyApp extends StatelessWidget {
final GoRouter router;
const MyApp({Key? key, required this.router}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routeInformationParser: router.routeInformationParser,
routerDelegate: router.routerDelegate,
);
}
}
Building Complex Route Structures
A major advantage of go_router
is its ability to support nested and dynamic routes. An example of a more complex structure with sub-routes could look like this:
final GoRouter _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => HomeScreen(),
routes: [
GoRoute(
path: 'profile/:username',
builder: (context, state) {
final username = state.params['username'];
return ProfileScreen(username: username);
},
),
GoRoute(
path: 'settings',
builder: (context, state) => SettingsScreen(),
),
],
),
],
);
Named Routes and Simple Navigation
Another feature of go_router
is the support for named routes. This allows you to navigate to routes by their names rather than paths, which is particularly useful in larger projects with many dynamic routes:
GoRoute(
name: 'profile',
path: '/profile/:username',
builder: (context, state) {
final username = state.params['username'];
return ProfileScreen(username: username);
},
);
You can now easily navigate to the profile page without manually specifying the path:
context.goNamed('profile', params: {'username': 'flutterdev'});
With go_router
, managing navigation in Flutter becomes significantly easier. The clear structure of routes and the straightforward handling of deep links make it the perfect choice for more complex apps.
Integrating Deep Links with go_router
The integration of deep links in a Flutter app using the go_router
library is an extremely efficient way to provide users with a seamless experience when navigating to specific content in your app via external links. go_router
employs a URL-based structure, making it simple to process deep links and adjust navigation accordingly.
Using Deep Links with go_router
Since go_router
natively supports URL-based navigation, you can directly connect deep links to the defined routes. When your app is opened via a deep link, go_router
recognizes the URL and navigates to the corresponding route.
Example of a Route Structure with Deep Links
Imagine you want your app to lead directly to a product through a deep link, for example, at the URL https://www.yourapp.com/product/123
. This can easily be achieved through a route with a dynamic parameter in go_router
:
final GoRouter _router = GoRouter(
routes: [
GoRoute(
path: '/',
builder: (context, state) => HomeScreen(),
),
GoRoute(
path: '/product/:id',
builder: (context, state) {
final id = state.params['id'];
return ProductDetailScreen(productId: id);
},
),
],
);
If your app is now opened via the deep link https://www.yourapp.com/product/123
, go_router
recognizes the URL, extracts the id
parameter, and displays the ProductDetailScreen
with ID 123
.
Handling URL Parameters and Query Parameters
go_router
also simplifies handling URL and query parameters. Suppose you want to pass additional information through query parameters in the URL, such as a sorting method for a product. The URL could look like this: https://www.yourapp.com/product/123?sort=price
.
To integrate this in go_router
, you can retrieve the query parameters from the state
object:
GoRoute(
path: '/product/:id',
builder: (context, state) {
final id = state.params['id'];
final sort = state.queryParams['sort'];
return ProductDetailScreen(productId: id, sortBy: sort);
},
);
With this code, you can use both the dynamic URL parameter id
and the query parameter sort
to adjust the corresponding view based on this information.
Automatically Navigating Based on Deep Links
go_router
automatically processes deep links as soon as your app is opened. You need to ensure that your routes are configured to properly handle the information contained in the links.
An example of automatic redirection based on a deep link:
GoRoute(
path: '/special-offer',
builder: (context, state) => SpecialOfferScreen(),
);
Now, when a user clicks on a deep link like https://www.yourapp.com/special-offer
, they will be directly redirected to the SpecialOfferScreen
, even if the app was closed.
Handling Non-Existent Deep Links
To ensure that users do not land on an empty page with invalid deep links, you can define a 404 page:
GoRouter(
errorBuilder: (context, state) => NotFoundScreen(),
);
When a user opens a deep link to an undefined route, go_router
automatically redirects them to the NotFoundScreen
instead of triggering an error. This enhances user experience and avoids frustration caused by invalid links.
Conclusion on Integrating Deep Links with go_router
The seamless integration of deep links with go_router
makes it significantly easier to direct users to specific content, regardless of whether the app is already open or not. By utilizing URL and query parameters, you can make navigation dynamic and flexible. This is especially helpful in applications that need to display complex routes and user-specific content. With the advanced features of go_router
, you can ensure that deep links in your app function not only efficiently but also user-friendly.
Conclusion
Deep linking and navigation are crucial components for a well-structured and user-friendly Flutter app. The correct implementation of deep links enhances the user experience by allowing users to access relevant content in the app, whether the app is already open or not. This is especially important for marketing campaigns, personalized notifications, and social media sharing.
With the go_router
library, Flutter offers an elegant and powerful way to implement complex navigation structures. Through a declarative approach to routing and seamless support for URL and query parameters, go_router
enables easy handling of deep links and dynamic routes. The combination of clear route management and the integration of redirects or error pages (e.g., 404 pages) ensures that your app remains stable even with unexpected links or user interactions.
Setting up deep links in Flutter may initially seem complex, especially due to platform-specific requirements for Android and iOS. However, by strategically using tools like go_router
, the process becomes significantly simplified and more efficient. This way, you can ensure that users receive the best user experience at all times – whether through direct links, dynamic routes, or a thoughtful navigation structure.
If you follow these best practices, your app will not only be more professional and user-friendly but also technically better prepared for complex use cases.
I would be happy to assist you in implementing deep linking and complex navigation structures in your Flutter app! Whether you need help setting up deep links or implementing go_router
for dynamic routes – I am here to help you move your project forward efficiently and professionally. Just reach out, and we will find the best solution for your app together!
All insights
All insights
“Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.”
“Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.”
Copyright ©2025. Julian Giesen. All rights reserved.
“Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.”