I'm trying to navigate to a route with StatefulShellRoute.indexedStack() implemented, and the problem in first instance is that I can't navigate to that view because StatefulShellRoute doens't let me use the path or name parameter, so i navigate to an internal view of main one.
It works ONLY in that view, if I try to switch to one of the branches that accompanies the branch i navigated, the application crashes because none of the other branches have the object i need to pass for the application to work.
The code of the routes implemented with the package go_router:
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
Empresa empresa = state.extra as Empresa;
return VistaGeneralEmpresa(
empresa: empresa,
navigationShell: navigationShell,
);
},
branches: <StatefulShellBranch>[
StatefulShellBranch(
navigatorKey: _rootNavigatorInicio,
routes: <RouteBase>[
GoRoute(
name: 'inicioEmpresa',
path: '/inicioEmpresa',
builder: (context, state) {
final Empresa empresa = state.extra as Empresa;
return VistaInicioEmpresa(empresa: empresa);
},
routes: [
GoRoute(
name: 'gestionInventario',
path: 'gestionInventario',
builder: (context, state) {
final Empresa empresa = state.extra as Empresa;
return VistaGeneralInventario(empresa);
}),
GoRoute(
name: 'historial',
path: 'historial',
builder: (context, state) {
final Empresa empresa = state.extra as Empresa;
return VistaHistorial(empresa: empresa);
}),
GoRoute(
name: 'estadisticas',
path: 'estadisticas',
builder: (context, state) {
final Empresa empresa = state.extra as Empresa;
return VistaEstadisticas(empresa: empresa);
}),
]),
],
),
StatefulShellBranch(
navigatorKey: _rootNavigatorCaja,
routes: <RouteBase>[
GoRoute(
path: '/caja',
builder: (context, state) {
final Empresa empresa = state.extra as Empresa;
return VistaCaja(empresa: empresa);
},
routes: []),
],
),
StatefulShellBranch(
navigatorKey: _rootNavigatorAjustes,
routes: <RouteBase>[
GoRoute(
path: '/ajustes',
builder: (context, state) {
final Empresa empresa = state.extra as Empresa;
return VistaAjustesEmpresa(empresa: empresa);
},
routes: [],
),
],
),
],
),
So with the code in hand, I try to navigate to VistaGeneralEmpresa, but since it's impossible, i just navigate to VistaInicioEmpresa. That works only for the nested views inside VistaInicioEmpresa, but if i try to go to VistaCaja or VistaAjustes, the app crashes with the mentioned error (empresa is null in VistaGeneralEmpresa).
I will show the implementation of the call to VistaInicioEmpresa() and the code of VistaGeneralEmpresa():
class VistaGeneralEmpresa extends StatefulWidget {
final Empresa empresa;
const VistaGeneralEmpresa({
super.key,
required this.empresa,
required this.navigationShell,
});
final StatefulNavigationShell navigationShell;
@override
State<VistaGeneralEmpresa> createState() => _VistaGeneralEmpresaState();
}
class _VistaGeneralEmpresaState extends State<VistaGeneralEmpresa> {
int selectedIndex = 0;
void _goBranch(int index) {
widget.navigationShell.goBranch(
index,
initialLocation: index == widget.navigationShell.currentIndex,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: widget.navigationShell,
),
bottomNavigationBar: GNav(
onTabChange: (value) {
setState(() {
selectedIndex = value;
_goBranch(selectedIndex);
});
},
selectedIndex: selectedIndex,
gap: 8,
backgroundColor: Colors.amberAccent,
color: const Color.fromARGB(255, 70, 70, 70),
activeColor: Colors.black,
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 20),
tabs: const [
GButton(
icon: Icons.home,
text: 'Inicio',
),
GButton(
icon: Icons.inventory,
text: 'Caja',
),
GButton(
icon: Icons.settings,
text: 'Ajustes',
)
],
),
);
}
}
Call to VistaInicioEmpresa:
void _navigateToVistaEmpresa(BuildContext context) {
context.goNamed("inicioEmpresa", extra: empresa);
}
Ok, so what i did to accomplish this situation is to make a method to call it where i want to make the navigation.
The method just updates the dummy object i created in the router class to use it in all the structure, and now, i can access every view without a problem.
static void actualizarEmpresa(Empresa em) {
empresaX = em;
}
I still call the inner view because the wrapper causes some problems, but with this solution, I mitigate the problem:
void _navigateToVistaEmpresa(BuildContext context) {
ControladorNavegacion.actualizarEmpresa(empresa);
context.push('/inicioEmpresa', extra: empresa);
}
And the routes looks almost the same:
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) {
return VistaGeneralEmpresa(
navigationShell: navigationShell,
);
},
branches: <StatefulShellBranch>[
StatefulShellBranch(
navigatorKey: _rootNavigatorInicio,
routes: <RouteBase>[
GoRoute(
name: 'inicioEmpresa',
path: '/inicioEmpresa',
builder: (context, state) {
//final Empresa empresa = empresaX;
return VistaInicioEmpresa(empresa: empresaX);
},
routes: [
GoRoute(
name: 'gestionInventario',
path: 'gestionInventario',
builder: (context, state) {
final Empresa empresa = state.extra as Empresa;
return VistaGeneralInventario(empresa);
}),
GoRoute(
name: 'historial',
path: 'historial',
builder: (context, state) {
final Empresa empresa = state.extra as Empresa;
return VistaHistorial(empresa: empresa);
}),
GoRoute(
name: 'estadisticas',
path: 'estadisticas',
builder: (context, state) {
final Empresa empresa = state.extra as Empresa;
return VistaEstadisticas(empresa: empresa);
}),
]),
],
),
StatefulShellBranch(
navigatorKey: _rootNavigatorCaja,
routes: <RouteBase>[
GoRoute(
path: '/caja',
builder: (context, state) {
//final Empresa empresa = state.extra as Empresa;
return VistaCaja(empresa: empresaX);
},
routes: []),
],
),
StatefulShellBranch(
navigatorKey: _rootNavigatorAjustes,
routes: <RouteBase>[
GoRoute(
path: '/ajustes',
builder: (context, state) {
//final Empresa empresa = state.extra as Empresa;
return VistaAjustesEmpresa(empresa: empresaX);
},
routes: [],
),
],
),
],
),