Open clragon opened 1 year ago
As far as I have understood that, the Route information is communicated by the RouteInformationProvider
.
To create a GoRouter that is disconnected from the global platform route, we would need a different version of the GoRouteInformationProvider
that does not listen to WidgetsBindingObserver
.
The RouteInformationProvider
would then simply maintain its Route in memory.
An example of an extremely crude version of this would look something like this:
class ValueRouteInformationProvider extends ValueNotifier<RouteInformation>
implements RouteInformationProvider {
ValueRouteInformationProvider({
required String initialRoute,
}) : super(RouteInformation(location: initialRoute));
@override
void routerReportsNewRouteInformation(RouteInformation routeInformation,
{RouteInformationReportingType type =
RouteInformationReportingType.none}) {}
}
To demonstrate what I mean, I have written a small piece of sample code with the Beamer
package, which already supports this, as it does not come with its own RouteInformationProvider
.
For other reasons, I would like to use GoRouter over Beamer.
https://github.com/flutter/flutter/assets/11785085/32c7b728-c740-4e3c-8a2d-3d3b7d9cbdb1
Note how the URL of my browser changes in the Platform tab, but not in the Virtual tab.
In both situations, the same router configuration is used, except for the RouteInformationProvider
.
As a temporary solution, I have also tried simply ignoring the GoRouteInformationProvider
like in this code snippet, which is currently not functional due to a runtime error:
This then throws the following:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building KeyedSubtree-[<0>]:
Assertion failed:
file:///<omitted>/Pub/Cache/hosted/pub.dev/go_router-9.0.3/lib/src/parser.dart:64:12
routeInformation.state != null
is not true
The relevant error-causing widget was:
TabBarView
When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 288:49 throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 29:3 assertFailed
packages/go_router/src/parser.dart 64:28 parseRouteInformationWithDependencies
packages/flutter/src/widgets/router.dart 704:12 [_processRouteInformation]
packages/flutter/src/widgets/router.dart 583:7 restoreState
packages/flutter/src/widgets/restoration.dart 912:5 [_doRestore]
packages/flutter/src/widgets/restoration.dart 898:7 didChangeDependencies
packages/flutter/src/widgets/router.dart 653:11 didChangeDependencies
packages/flutter/src/widgets/framework.dart 5237:11 [_firstBuild]
Which I assume is because GoRouter expects its RouteInformationParser
to specifically be a GoRouteInformationProvider
that has a certain behaviour.
I have done some extra research, and it is purely technically already possible to create such a GoRouter without modifying the package, by copying some of the source code and extending it. The following code:
This works by removing the links between WidgetsBinding
and the GoRouteInformationProvider
and GoRouter
by making all communication a no-op.
This demonstrates the behaviour I would like very clearly.
I dont think however that a destructive override from the outside like this would be a nice solution and I would like a solution to be available inside the package, as proposed originally.
ShellRoute
is used to draw UI elements around certain paths.
It's functionality is not equivalent to having a separate router with it's entirely own path.
I can think of several way to do this.
hey👋🏻 @clragon
so i have a similar usecase where i'm implementing a browser-like tabs feature.
thankfully i got it working using a StatefulShellBranch
for each tab. (ofc the router has to be updated at runtime).
Now my question is: does using a separate router has a performance advantage?? or it's just a better way to manage each tab(router) history.
PS: i haven't got the chance YET to dig deeper into how things work under the hood. so i just wanted to know if there's a reason u went with this design choice.
✌
@DMouayad Hi, Would you mind to share an example of how to implement dynamic browser-like tabs navigation using StatefulShellBranch
?
Is there an existing issue for this?
Use case
My app works more like a Web Browser than a single Web Page. As such, I would like to use mutliple Routers in my App, one for each "tab". Each tab then has its own route, completely independant of other tabs.
GoRouter would work great for this, but its always connected to the global platform route itself.
Conceptually, Routers are allowed to be arbitrarily nested and can be disconnected from the platforms route to maintain their own route instead, as per documentation.
Proposal
It would be nice if it was possible to disconnect a GoRouter from the platform route. With this, it would be possible to maintain multiple GoRouters throughout an app, which would be a great addition.