我正在寻找一种方法来根据登录状态在应用启动时显示不同的屏幕。例如,我定义了以下路由:
自然,我将检查用户是否已经使用main()
方法登录,然后将我的MaterialApp的initialRoute
设置为/ login或/ home。成功登录后,我可以调用Navigator.pushReplacement
导航到/ home,并从堆栈中删除登录屏幕。不幸的是,我总是必须为/
定义一个路由或设置MaterialApp的home
属性。因此,如果我将/
设置为空白的Container()
,则此Container将在导航堆栈中,并且用户可以返回到该空白屏幕。
我想到的两个选择是:
build()
方法返回LoginScreen 这两个选项都是可行的,但是为了更新home属性或HomeScreen,我必须提出一些重载逻辑并重新设置状态。
有什么想法在Flutter中处理此类案件的正确方法是什么?
答案 0 :(得分:2)
也许您可以这样做。想象一下,您有一个带有异步方法isLogged
的Auth类。
class Auth {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Future<bool> isLogged() async {
try {
final FirebaseUser user = await _firebaseAuth.currentUser();
return user != null;
} catch (e) {
return false;
}
}
}
您可以使用myApp
构造函数传递initialRoute
,并根据登录状态决定初始路由。然后,您可以将myApp
的实例传递给runApp
:
void main() async {
final Auth _auth = Auth();
final bool isLogged = await _auth.isLogged();
final MyApp myApp = MyApp(
initialRoute: isLogged ? '/home' : '/',
);
runApp(myApp);
}
然后,您必须修改myApp
类以在构造函数中传递初始路由:
class MyApp extends StatelessWidget {
final String initialRoute;
MyApp({this.initialRoute});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dynamic Route Demo',
initialRoute: initialRoute,
routes: {
'/': (context) => LoginPage(),
'/home': (context) => HomePage(),
'/settings': (context) => SettingsPage(),
},
);
}
}
希望这会有所帮助。
答案 1 :(得分:0)
您应该做的是移动到/ login路由(或其他您喜欢的登录名),并将其设置为initialRoute。基于此,您可以修改应用程序的onGenerateInitialRoutes属性,以确保实际上没有将路由推送到导航器历史记录中。这样,您将覆盖defaultGenerateInitialRoutes,它会将这些原始状态推送到导航器。在Flutter网站上检查此代码段。
https://api.flutter.dev/flutter/widgets/Navigator/defaultGenerateInitialRoutes.html
也将其复制到此处,以防万一将来链接不可用。
defaultGenerateInitialRoutes方法列表 defaultGenerateInitialRoutes(NavigatorState导航器,字符串 initialRouteName)将路由名称转换为一组Route对象。
这是onGenerateInitialRoutes的默认值,如果 initialRoute不为null。
如果此字符串包含任何/字符,则将字符串拆分为 从字符串开头到最后的那些字符和子字符串 每个这样的角色又被用作推入路线。
例如,如果将路径/ stocks / HOOLI用作初始路径, 然后导航器将在启动时推送以下路线:/, / stocks,/ stocks / HOOLI。这样可以进行深层链接,同时允许 维护可预测的路线历史的应用程序。
static List<Route<dynamic>> defaultGenerateInitialRoutes(NavigatorState navigator, String initialRouteName) {
final List<Route<dynamic>> result = <Route<dynamic>>[];
if (initialRouteName.startsWith('/') && initialRouteName.length > 1) {
initialRouteName = initialRouteName.substring(1); // strip leading '/'
assert(Navigator.defaultRouteName == '/');
List<String> debugRouteNames;
assert(() {
debugRouteNames = <String>[ Navigator.defaultRouteName ];
return true;
}());
result.add(navigator._routeNamed<dynamic>(Navigator.defaultRouteName, arguments: null, allowNull: true));
final List<String> routeParts = initialRouteName.split('/');
if (initialRouteName.isNotEmpty) {
String routeName = '';
for (final String part in routeParts) {
routeName += '/$part';
assert(() {
debugRouteNames.add(routeName);
return true;
}());
result.add(navigator._routeNamed<dynamic>(routeName, arguments: null, allowNull: true));
}
}
if (result.last == null) {
assert(() {
FlutterError.reportError(
FlutterErrorDetails(
exception:
'Could not navigate to initial route.\n'
'The requested route name was: "/$initialRouteName"\n'
'There was no corresponding route in the app, and therefore the initial route specified will be '
'ignored and "${Navigator.defaultRouteName}" will be used instead.'
),
);
return true;
}());
result.clear();
}
} else if (initialRouteName != Navigator.defaultRouteName) {
// If initialRouteName wasn't '/', then we try to get it with allowNull:true, so that if that fails,
// we fall back to '/' (without allowNull:true, see below).
result.add(navigator._routeNamed<dynamic>(initialRouteName, arguments: null, allowNull: true));
}
// Null route might be a result of gap in initialRouteName
//
// For example, routes = ['A', 'A/B/C'], and initialRouteName = 'A/B/C'
// This should result in result = ['A', null,'A/B/C'] where 'A/B' produces
// the null. In this case, we want to filter out the null and return
// result = ['A', 'A/B/C'].
result.removeWhere((Route<dynamic> route) => route == null);
if (result.isEmpty)
result.add(navigator._routeNamed<dynamic>(Navigator.defaultRouteName, arguments: null));
return result;
}