initialRoute 字符串已更改,但无论 initialRoute 字符串如何,我最终都会到达同一页面
initialRoute string is changed, but I end up at the same page regardless the initialRoute string
当在 main.dart 的 flutter 上使用 shared_preferences 以根据用户是否看到第一页或用户是否登录来更改 initialRoute 时,我得到了在整个过程中创建的布尔值应用程序并添加到 shared_preferences,每次我启动应用程序时,调试时我都会得到正确的 initialRoute 字符串,但无论条件如何,我最终还是会进入第一页。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:developer';
import './pages/registration.dart';
import './pages/login_page.dart';
import './pages/confirmation.dart';
import './pages/lang_page.dart';
import './pages/main_page.dart';
import './pages/user_data.dart';
import './provider/provider.dart';
void main() => runApp(CallInfoApp());
class CallInfoApp extends StatefulWidget {
@override
_CallInfoAppState createState() => _CallInfoAppState();
}
class _CallInfoAppState extends State<CallInfoApp> {
SharedPreferences prefs;
void getSPInstance() async {
prefs = await SharedPreferences.getInstance();
}
dynamic langChosen;
dynamic isLoggedIn;
String initialRoute;
void dataGetter() async {
await getSPInstance();
setState(() {
langChosen = prefs.getBool('langChosen');
// print(langChosen);
isLoggedIn = prefs.getBool('isLoggedIn');
});
}
void getRoute() async {
await dataGetter();
debugger();
if (langChosen == true && isLoggedIn != true) {
setState(() {
initialRoute = '/login_page';
});
} else if (isLoggedIn == true) {
initialRoute = '/main_page';
} else {
setState(() {
initialRoute = '/';
});
}
}
@override
void initState() {
super.initState();
debugger();
getRoute();
}
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
return ChangeNotifierProvider<AppData>(
create: (context) => AppData(),
child: MaterialApp(
title: 'Call-INFO',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: initialRoute,
routes: {
'/': (context) => LanguagePage(),
'/registration_page': (context) => RegistrationPage(),
'/login_page': (context) => LoginPage(),
'/confirmation_page': (context) => ConfirmationPage(),
'/user_data_page': (context) => UserDataPage(),
'/main_page': (context) => MainPage(),
},
),
);
}
}
使用 initState
导出您的逻辑所基于的数据(即获取共享偏好信息)。并使用 await
关键字,以便程序将等待数据从 SharedPrefs 中获取。将以下代码添加到 class _CallInfoAppState 应该会有所帮助
@override
void initState() {
super.initState();
dataGetter();
}
void dataGetter() async {
await getSPInstance();
setState(() {
langChosen = prefs.getBool('langChosen');
isLoggedIn = prefs.getBool('isLoggedIn');
});
}
由于 SharedPreference.getInstance() 是一个异步函数,它需要一些时间才能使实例可用。如果你想将它用于初始路由,你必须在你的 MaterialApp 构建之前让你的主函数异步并预加载它。
SharedPreference prefs; //make global variable, not best practice
void main() async {
prefs = await SharedPreference.getInstance();
runApp(CallInfoApp());
}
并从 dataGetter 中删除 getSPInstance()
另外请注意,如果没有条目进入共享首选项,prefs.getBool('langChosen') 将 return 为 null 而不是 false,因此请使用
langChosen = prefs.getBool('langChosen')??false;
isLoggedIn = prefs.getBool('isLoggedIn')??false;
虽然此解决方案可行,但并不是很好的做法。我建议将 initialRoute 固定到初始屏幕并从那里处理转发到正确的页面。一个简单的启动画面可能如下所示:
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(body: Center(child: CircularProgressIndicator()));
}
@override
void initState() {
initSplash();
super.initState();
}
Future<void> initSplash() async {
final prefs = await SharedPreferences.getInstance();
final langChosen = prefs.getBool("lang_chosen") ?? false;
final isLoggedIn = prefs.getBool("logged_in") ?? false;
if (langChosen == true && isLoggedIn != true) {
Navigator.of(context).pushReplacementNamed('/login_page');
} else if (isLoggedIn == true) {
Navigator.of(context).pushReplacementNamed('/main_page');
} else {
Navigator.of(context).pushReplacementNamed('/');
}
}
}
当在 main.dart 的 flutter 上使用 shared_preferences 以根据用户是否看到第一页或用户是否登录来更改 initialRoute 时,我得到了在整个过程中创建的布尔值应用程序并添加到 shared_preferences,每次我启动应用程序时,调试时我都会得到正确的 initialRoute 字符串,但无论条件如何,我最终还是会进入第一页。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:developer';
import './pages/registration.dart';
import './pages/login_page.dart';
import './pages/confirmation.dart';
import './pages/lang_page.dart';
import './pages/main_page.dart';
import './pages/user_data.dart';
import './provider/provider.dart';
void main() => runApp(CallInfoApp());
class CallInfoApp extends StatefulWidget {
@override
_CallInfoAppState createState() => _CallInfoAppState();
}
class _CallInfoAppState extends State<CallInfoApp> {
SharedPreferences prefs;
void getSPInstance() async {
prefs = await SharedPreferences.getInstance();
}
dynamic langChosen;
dynamic isLoggedIn;
String initialRoute;
void dataGetter() async {
await getSPInstance();
setState(() {
langChosen = prefs.getBool('langChosen');
// print(langChosen);
isLoggedIn = prefs.getBool('isLoggedIn');
});
}
void getRoute() async {
await dataGetter();
debugger();
if (langChosen == true && isLoggedIn != true) {
setState(() {
initialRoute = '/login_page';
});
} else if (isLoggedIn == true) {
initialRoute = '/main_page';
} else {
setState(() {
initialRoute = '/';
});
}
}
@override
void initState() {
super.initState();
debugger();
getRoute();
}
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
return ChangeNotifierProvider<AppData>(
create: (context) => AppData(),
child: MaterialApp(
title: 'Call-INFO',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: initialRoute,
routes: {
'/': (context) => LanguagePage(),
'/registration_page': (context) => RegistrationPage(),
'/login_page': (context) => LoginPage(),
'/confirmation_page': (context) => ConfirmationPage(),
'/user_data_page': (context) => UserDataPage(),
'/main_page': (context) => MainPage(),
},
),
);
}
}
使用 initState
导出您的逻辑所基于的数据(即获取共享偏好信息)。并使用 await
关键字,以便程序将等待数据从 SharedPrefs 中获取。将以下代码添加到 class _CallInfoAppState 应该会有所帮助
@override
void initState() {
super.initState();
dataGetter();
}
void dataGetter() async {
await getSPInstance();
setState(() {
langChosen = prefs.getBool('langChosen');
isLoggedIn = prefs.getBool('isLoggedIn');
});
}
由于 SharedPreference.getInstance() 是一个异步函数,它需要一些时间才能使实例可用。如果你想将它用于初始路由,你必须在你的 MaterialApp 构建之前让你的主函数异步并预加载它。
SharedPreference prefs; //make global variable, not best practice
void main() async {
prefs = await SharedPreference.getInstance();
runApp(CallInfoApp());
}
并从 dataGetter 中删除 getSPInstance()
另外请注意,如果没有条目进入共享首选项,prefs.getBool('langChosen') 将 return 为 null 而不是 false,因此请使用
langChosen = prefs.getBool('langChosen')??false;
isLoggedIn = prefs.getBool('isLoggedIn')??false;
虽然此解决方案可行,但并不是很好的做法。我建议将 initialRoute 固定到初始屏幕并从那里处理转发到正确的页面。一个简单的启动画面可能如下所示:
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(body: Center(child: CircularProgressIndicator()));
}
@override
void initState() {
initSplash();
super.initState();
}
Future<void> initSplash() async {
final prefs = await SharedPreferences.getInstance();
final langChosen = prefs.getBool("lang_chosen") ?? false;
final isLoggedIn = prefs.getBool("logged_in") ?? false;
if (langChosen == true && isLoggedIn != true) {
Navigator.of(context).pushReplacementNamed('/login_page');
} else if (isLoggedIn == true) {
Navigator.of(context).pushReplacementNamed('/main_page');
} else {
Navigator.of(context).pushReplacementNamed('/');
}
}
}