Flutter main.dart出现LateInitializationError及SharedPreferences双登录处理问题
LateInitializationError 报错修复
报错原因
你声明的late bool userLoggedIn为延迟初始化变量,getLoggedInState属于异步方法,initState调用该方法后不会等待异步逻辑执行完成,就会触发首次build渲染,此时userLoggedIn还未完成赋值,就会触发延迟初始化报错。
你所说的bool? userLoggedIn写法不被Flutter允许,本质是你未处理可空变量的空值判断逻辑,直接将可空变量用于页面路由判断导致的编译错误。
修复后的完整代码
void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { // 改为可空类型,空值代表还未读取到登录状态 bool? userLoggedIn; @override void initState() { getLoggedInState(); super.initState(); } getLoggedInState() async { final value = await HelperFunctions.getUserLoggedInSharedPreference(); setState(() { // 处理空值默认逻辑,未读取到状态时默认视为未登录 userLoggedIn = value ?? false; }); } @override Widget build(BuildContext context) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); return MaterialApp( debugShowCheckedModeBanner: false, title: 'Dashee', theme: ThemeData( primarySwatch: Colors.deepPurple, ), // 先判断是否读取到状态,未读取到时优先显示启动页 home: userLoggedIn == null ? const Splash() : (userLoggedIn! ? const Dashboard() : const Login())); } }
注意:如果原来的未登录跳转页不是Login可以自行替换为你项目中的对应页面
双登录场景(比如普通用户/商家、个人账号/企业账号两类身份登录)的处理逻辑如下:
- 存储登录信息时,除了存储
是否登录的布尔值,额外新增登录身份类型字段,比如用整数标识:0代表普通用户,1代表商家 - 读取登录状态时,同步读取登录身份字段,根据两个字段的结果判断跳转对应身份的首页
- 退出登录时,需要同时清空登录状态、登录身份两个字段,避免数据残留导致逻辑错误
工具类示例代码
class HelperFunctions { static String userLoggedInKey = "USERLOGGEDINKEY"; static String loginTypeKey = "LOGINTYPEKEY"; // 0=普通用户 1=商家 // 保存登录信息 static Future<void> saveLoginInfo(bool isLoggedIn, int type) async { SharedPreferences sp = await SharedPreferences.getInstance(); await sp.setBool(userLoggedInKey, isLoggedIn); await sp.setInt(loginTypeKey, type); } // 读取登录状态 static Future<bool?> getUserLoggedInSharedPreference() async { SharedPreferences sp = await SharedPreferences.getInstance(); return sp.getBool(userLoggedInKey); } // 读取登录身份 static Future<int?> getLoginType() async { SharedPreferences sp = await SharedPreferences.getInstance(); return sp.getInt(loginTypeKey); } // 清空登录信息(退出登录时调用) static Future<void> clearLoginInfo() async { SharedPreferences sp = await SharedPreferences.getInstance(); await sp.remove(userLoggedInKey); await sp.remove(loginTypeKey); } }
调整路由判断逻辑
修改getLoggedInState方法和路由判断即可:
class _MyAppState extends State<MyApp> { bool? userLoggedIn; int? loginType; getLoggedInState() async { final loggedIn = await HelperFunctions.getUserLoggedInSharedPreference(); final type = await HelperFunctions.getLoginType(); setState(() { userLoggedIn = loggedIn ?? false; loginType = type; }); } @override Widget build(BuildContext context) { SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); return MaterialApp( debugShowCheckedModeBanner: false, title: 'Dashee', theme: ThemeData( primarySwatch: Colors.deepPurple, ), home: userLoggedIn == null ? const Splash() : !userLoggedIn! ? const Login() : (loginType == 0 ? const UserDashboard() : const MerchantDashboard())); } }
内容的提问来源于stack exchange,提问作者Ali umer
相关产品推荐
相关产品推荐

