flutter_deep_linking 0.2.1
flutter_deep_linking: ^0.2.1 copied to clipboard
π§ Describe your routing declaratively and handle deep links properly!
π§ Handle all your routing with proper deep links and handle them declaratively!
What this package is about #
This package takes declaratively defined Route
s and receives a URI during navigation, evaluates those and then returns a PageRoute
for the correct page. This means, you can now benefit from loose coupling and navigate using:
Navigator.of(context).pushNamed('/articles/$id')
instead of hardcoding the corresponding widget everytime:
Navigator.of(context)
.push(MaterialPageRoute(builder: (_) => ArticlePage(id)));
What this package is not about #
This package doesn't catch incoming deep links from other apps. For this, I recommend uni_links.
You can, however, combine both packages. Just forward any received deep links to your Navigator
and flutter_deep_linking
takes care of resolving them. This also works with the initial deep link:
String initialLink = await getInitialLink(); // from uni_links
return MaterialApp(
initialRoute: initialLink,
onGenerateRoute: router.onGenerateRoute, // from flutter_deep_linking
// ...
);
Getting started #
1. π§ Create a Router
containing all your routes: #
final router = Router(
routes: [
Route(
// This matches any HTTP or HTTPS URI pointing to schul-cloud.org.
// Due to `isOptional`, this also matches URIs without a scheme or domain,
// but not other domains.
matcher: Matcher.webHost('schul-cloud.org', isOptional: true),
// These nested routes are evaluated only if the above condition matches.
routes: [
Route(
matcher: Matcher.path('courses'),
materialBuilder: (_, __) => CoursesPage(),
routes: [
// If this route matches, it is used. Otherwise, we fall back to the
// outer courses-route.
Route(
// {courseId} is a parameter matches a single path segment.
matcher: Matcher.path('{courseId}'),
materialBuilder: (_, RouteResult result) {
// You can access the matched parameters using `result[<name>]`.
return CourseDetailPage(result['courseId']);
},
),
],
),
Route(
// Matcher.path can also match nested paths.
matcher: Matcher.path('user/settings'),
materialBuilder: (_, __) => SettingsPage(),
),
],
),
// This route doesn't specify a matcher and hence matches any route.
Route(
materialBuilder: (_, RouteResult result) => NotFoundPage(result.uri),
),
],
);
Note: Flutter also defines classes called
Route
&RouteBuilder
which can lead to some confusion. If you importpackage:flutter/widgets.dart
in the same file asflutter_deep_linking
, you can ignore Flutter'sRoute
&RouteBuilder
withimport 'package:flutter/widgets.dart' hide Route, RouteBuilder;
.
Router
accepts a list of Route
s which are searched top to bottom, depth first. Using Matcher
s you can match parts of the URI. Inner Matcher
s can't access parts of the URI that have already been matched by an outer Matcher
.
To build the actual page, you can specify either of:
Route.builder
: Takes aRouteResult
and returns an instance of Flutter'sRoute
.Route.materialBuilder
(Convenience property): Takes a [BuildContext
] and aRouteResult
and returns a widget, which is then wrapped inMaterialPageRoute
.
2. π― Let your Router
take care of resolving URIs in MaterialApp
(or CupertinoApp
or a custom Navigator
): #
MaterialApp(
onGenerateRoute: router.onGenerateRoute,
// ...
)
3. π Use your new routes! #
When navigating, use navigator.pushNamed(uriString)
instead of calling navigator.push(builder)
and benefit from loose coupling!
And if you build an app in addition to a website, you can use a package like uni_links to receive incoming links and directly forward them to flutter_deep_linking
.
More information #
Matcher
s #
Available Matcher
s:
Matcher.scheme
: Matches a URI scheme likehttps
.Matcher.webScheme
: Conveniently matcheshttp
orhttps
.Matcher.host
: Matches a URI host likeschul-cloud.org
.Matcher.webHost
: Conveniently matches awebScheme
(see above) and a URI host.Matcher.path
: Matches a single or multiple URI path segments likecourses/{courseId}
, whereascourseId
is a placeholder and will match exactly one segment.
You can also combine Matcher
s within a single Route
:
matcher1 & matcher2
matches bothMatcher
s in sequence.matcher1 | matcher2
evaluates bothMatcher
s in sequence and returns the first match.
RouteResult
#
RouteResult
most importantly contains:
uri
: The initial URI (which can be used, e.g., to access query parameters).parameters
: AMap<String, String>
of matched parameters, also accessible viaresult[<name>]
.settings
: TheRouteSettings
that should be forwarded to the generated (Flutter)Route
.