Open annawidera opened 1 year ago
Update: I discovered that using uni_link
for reading in the deep link intent + opting out from flutter_deeplinking_enabled
made it possible to orchestrate the traffic between tabs.
<meta-data android:name="flutter_deeplinking_enabled" android:value="false" />
class _AppScreenState extends State<AppScreen> {
late int currentIndex;
StreamSubscription? _sub;
@override
void initState() {
super.initState();
// listening to links stream from uni_links was added
_sub = uriLinkStream.listen(
(Uri? uri) {
if (uri != null) {
// Handcrafted uri parsing, and handling forwarded to the **right** delegate
if (uri.path.contains('books')) {
routerDelegates[0].beamToNamed(uri.path);
setState(() => currentIndex = 0);
} else if (uri.path.contains('articles')) {
routerDelegates[1].beamToNamed(uri.path);
setState(() => currentIndex = 1);
}
}
},
onError: (err) {
print("uriLinkStream error! $err");
// Handle exception by warning the user their action did not succeed
},
);
}
@override
void dispose() {
_sub?.cancel();
super.dispose();
}
// exactly as they were in example: 'bottom_navigation_multiple_beamers'
final routerDelegates = [
BeamerDelegate(
initialPath: '/books',
locationBuilder: (routeInformation, _) {
if (routeInformation.location!.contains('books')) {
return BooksLocation(routeInformation);
}
return NotFound(path: routeInformation.location!);
},
),
BeamerDelegate(
initialPath: '/articles',
locationBuilder: (routeInformation, _) {
if (routeInformation.location!.contains('articles')) {
return ArticlesLocation(routeInformation);
}
return NotFound(path: routeInformation.location!);
},
),
];
@override
void didChangeDependencies() {
// exactly as in example: 'bottom_navigation_multiple_beamers'
}
@override
Widget build(BuildContext context) {
// exactly as in example: 'bottom_navigation_multiple_beamers'
}
}
Is this the way to do deep linking with multiple Beamers on Android?
On iOS, I didn't have to opt-out from FlutterDeepLinkingEnabled
to make this work even without uni_links
and manual URI parsing and picking the right routerDelegate
for the deep link to handle.
Does anybody know where the difference is between delivering the deep links when FlutterDeepLinkingEnabled
is enabled on iOS and Android? How may this confuse Beamer
?
Thank you that solved my problem ! Only difference is that I am using Cubit instead of Stateful widget to update index
Hey @annawidera :wave: Thanks for creating a wonderfully elaborated issue and sorry for my absence lately. Also, thanks for the kind words :slightly_smiling_face:
This is a good solution. Nevertheless, working with tabs often causes confusion because they are tricky from routing perspective. That's why I'm planing to add additional support for tab control - #618
Another thing I can additionally suggest for preserving the state of tabs while the app is running and receives the link is the following:
Instead of
routes: {
'*': (context, state, data) => AppScreen(),
},
we can do
routes: {
'*': (context, state, data) => BeamPage(
key: ValueKey('app'),
child: AppScreen(),
),
},
which will prevent the rebuild of the entire app and therefore losing what the state of tabs (scroll, navigation, ...). This works because Navigator will only rebuild the page if the key has changed. If we keep it constant, then we will never rebuild AppScreen, but will react to routes because we have listeners on root Beamer.
Hey @slovnicki ! Thank you for the fantastic navigation package! I've tried a couple of them already 🙈 and
Beamer
appears to have a well-thought-through structure. It also has the balance between automating things and not being a pure 🔮 black box. I also appreciate an extensive catalogue of examples. I found a few solutions for the navigation I need: the bottom tab bar.Background: requirements
preserving tabs state
An essential requirement, in my case, is to preserve the state of the tabs (their nested navigation) while switching between them. So I based my experiments on
bottom_navigation_multiple_beamers
example.deep linking to nested pages
Another feature that we need is
deep linking
that navigates to the nested pages in the tabs (like for examplebooks/2
orarticles/3
).Changes to the example
I added
deep link
support by adding the following:to the
examples/bottom_navigation_multiple_beamers/android/app/src/main/AndroidManifest.xml
.Full AndroidManifest.xml content
``` XMLCurrent behaviour
On Android, when sending an
intent
from the terminal:Makes the first tab (
Books
) present theDetails page
with the 1st book. 👍🏻 Unfortunately, the state of the other tab (Articles
) is lost. 👎🏻What I have already found
So far, I discovered that it happens becase the intent
/books/1
is sent to the mainBeamer
, and it passes it (?) down to bothBeamerDelegates
(that are part of theAppScreenState
):Both
locationBuilders
are called. For/books/1
, the firstBeamerDelegate
shows the detail page, but the second one has to returnNotFound(path: routeInformation.location!);
and its state is lost.Expected behaviour + question
How can I ensure that only relevant
BeamerDelegate's
locationBuilder
is called when handling a deep link intent? In the case of my example, this would beBeamerDelegate
for/books
.Shall I try another configuration, and specify the tabs' routes in the top-level
routerDelegate
?Please let me know if I can provide any further details! Thanks for any advice!