Al fin después de tanto luchar pudimos dar con el resultado de esta impedimento que muchos usuarios de este sitio web presentan. Si tienes algún dato que aportar no dudes en dejar tu conocimiento.
Solución:
Yo también estaba tropezando con este problema y terminé usando un FutureBuilder
para esto. Echa un vistazo a mis rutas:
final routes =
'/': (BuildContext context) => FutureBuilder(
// This is my async call to sharedPrefs
future: AuthProvider.of(context).authState$.skipWhile((_) => _ == null).first,
builder: (BuildContext context, AsyncSnapshot snapshot)
switch(snapshot.connectionState)
case ConnectionState.done:
// When the future is done I show either the LoginScreen
// or the requested Screen depending on AuthState
return snapshot.data == AuthState.SIGNED_IN ? JobsScreen() : LoginScreen()
default:
// I return an empty Container as long as the Future is not resolved
return Container();
,
),
;
Si desea reutilizar el código en varias rutas, puede ampliar FutureBuilder.
No creo que exista un mecanismo de protección de ruta per se, pero puede hacer lógica en el main
función antes de cargar la aplicación, o utilice la onGenerateRoute
propiedad de un MaterialApp
. Una forma de hacerlo en su caso es esperar una función asincrónica que verifique si el usuario está conectado antes de cargar la ruta inicial. Algo como
main()
fetchUser().then((user)
if (user != null) runApp(MyApp(page: 'home'));
else runApp(MyApp(page: 'login'));
);
Pero también puede estar interesado en la forma en que lo hace la aplicación Shrine. Tienen la página de inicio de sesión como ruta inicial en cualquier caso y la eliminan si el usuario ha iniciado sesión. De esa manera, el usuario ve la página de inicio de sesión hasta que se haya determinado si inicia sesión o no. He incluido el fragmento relevante a continuación. .
class ShrineApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Shrine',
home: HomePage(),
initialRoute: '/login',
onGenerateRoute: _getRoute,
);
Route _getRoute(RouteSettings settings)
if (settings.name != '/login')
return null;
return MaterialPageRoute(
settings: settings,
builder: (BuildContext context) => LoginPage(),
fullscreenDialog: true,
);
Si no desea que vean la página de inicio de sesión en absoluto si están registrados, utilice el primer enfoque y podrá controlar la pantalla de inicio que se muestra antes. runApp
tiene una interfaz de usuario explorando esta respuesta.
Se me ocurrió la siguiente solución para un proyecto web, que me permite introducir fácilmente rutas protegidas sin tener que preocuparme de que un usuario no autorizado pueda acceder a información confidencial.
La clase GuardedRoute tiene este aspecto:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:kandabis_core/core.dart' as core;
Widget _defaultTransitionsBuilder(
BuildContext context,
Animation animation,
Animation secondaryAnimation,
Widget child)
return child;
class GuardedRoute extends PageRouteBuilder
GuardedRoute(
@required final String guardedRoute,
@required final String fallbackRoute,
@required final Stream guard,
@required final core.Router router,
final RouteTransitionsBuilder transitionsBuilder = _defaultTransitionsBuilder,
final bool maintainState = true,
final Widget placeholderPage,
)
: super(
transitionsBuilder: transitionsBuilder,
maintainState: maintainState,
pageBuilder: (context, animation, secondaryAnimation) =>
StreamBuilder(
stream: guard,
builder: (context, snapshot)
if (snapshot.hasData)
// navigate to guarded route
if (snapshot.data == true)
return router.routes[guardedRoute](context);
// navigate to fallback route
return router.routes[fallbackRoute](context);
// show a placeholder widget while the guard stream has no data yet
return placeholderPage ?? Container();
),
);
Usar la ruta vigilada es fácil. Puede definir una ruta protegida y una ruta alternativa (como una página de inicio de sesión). Guard es un Stream que decide si el usuario puede navegar a la ruta protegida. esta es mi clase de enrutador que muestra cómo usar la clase GuardedRoute:
class BackendRouter extends core.BackendRouter
BackendRouter(
this._authenticationProvider,
this._logger
);
static const _tag = "BackendRouter";
core.Lazy> _navigatorKey =
core.Lazy(() => GlobalKey());
final core.AuthenticationProvider _authenticationProvider;
final core.Logger _logger;
@override
Map get routes =>
core.BackendRoutes.main: (context) => MainPage(),
core.BackendRoutes.login: (context) => LoginPage(),
core.BackendRoutes.import: (context) => ImportPage(),
;
@override
Route onGenerateRoute(RouteSettings settings)
if (settings.name == core.BackendRoutes.login)
return MaterialPageRoute(
settings: settings,
builder: routes[settings.name]
);
return _guardedRoute(settings.name);
@override
GlobalKey get navigatorKey => _navigatorKey();
@override
void navigateToLogin()
_logger.i(_tag, "navigateToLogin()");
navigatorKey
.currentState
?.pushNamed(core.BackendRoutes.login);
@override
void navigateToImporter()
_logger.i(_tag, "navigateToImporter()");
navigatorKey
.currentState
?.pushReplacement(_guardedRoute(core.BackendRoutes.import));
GuardedRoute _guardedRoute(
String route,
maintainState = true,
fallbackRoute = core.BackendRoutes.login,
) =>
GuardedRoute(
guardedRoute: route,
fallbackRoute: fallbackRoute,
guard: _authenticationProvider.isLoggedIn(),
router: this,
maintainState: maintainState,
placeholderPage: SplashPage(),
);
Y su clase de aplicación se ve así:
class BackendApp extends StatelessWidget
@override
Widget build(BuildContext context)
// get router via dependency injection
final core.BackendRouter router = di.get();
// create app
return MaterialApp(
onGenerateRoute: (settings) => router.onGenerateRoute(settings),
navigatorKey: router.navigatorKey,
);
Sección de Reseñas y Valoraciones
Recuerda que te brindamos la opción de agregar una reseña si tropezaste tu impedimento a tiempo.