Flutter SharedPreferences非空实例字段未初始化报错如何解决?
问题原因
该报错是Dart空安全机制导致的:非空类型的实例字段必须在构造执行完成前完成初始化,你当前的sharedPreferences是在异步方法checkLoginStatus里赋值,Dart无法保证你在访问这个变量前已经完成赋值,所以抛出编译错误。
解决方案
你可以根据业务场景选择以下任意一种方案修复:
方案1:使用late关键字声明延迟初始化
当你可以确认在任何访问sharedPreferences的场景前,变量已经完成赋值的前提下,直接给变量添加late修饰符即可。
把原代码的SharedPreferences sharedPreferences;修改为late SharedPreferences sharedPreferences;。
你的代码场景中initState就触发了checkLoginStatus异步方法,且build阶段、点击事件触发时变量已经完成赋值,该方案适用。方案2:声明为可空类型
如果你不确定变量赋值时机,可将其声明为可空类型,使用时做非空校验:
声明修改为:SharedPreferences? sharedPreferences;
所有使用的地方添加非空处理(确认已赋值的场景可直接加非空断言!),示例如下:onPressed: () { sharedPreferences?.clear(); sharedPreferences?.commit(); Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => LoginPage()), (Route<dynamic> route) => false); },方案3:全局提前初始化SharedPreferences(更推荐)
你可以在main函数中提前完成SharedPreferences的初始化,避免每个页面单独处理异步赋值逻辑,修改后的完整代码如下:import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; import 'package:login/login_page.dart'; import 'package:shared_preferences/shared_preferences.dart'; // 全局SharedPreferences实例,所有页面可直接调用 late SharedPreferences globalSp; void main() async { // 确保Flutter框架初始化完成 WidgetsFlutterBinding.ensureInitialized(); // 提前初始化SharedPreferences globalSp = await SharedPreferences.getInstance(); runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: "Code Land", debugShowCheckedModeBanner: false, home: MyHomePage(), theme: ThemeData( accentColor: Colors.white70 ), ); } } class MyHomePage extends StatefulWidget { @override createState() => MyHomePageState(); } class MyHomePageState extends State<MyHomePage> { @override void initState() { super.initState(); checkLoginStatus(); } checkLoginStatus() async { if(globalSp.getString("token") == null) { Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => LoginPage()), (Route<dynamic> route) => false); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Code Land", style: TextStyle(color: Colors.white)), actions: <Widget>[ FlatButton( onPressed: () { globalSp.clear(); globalSp.commit(); Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) => LoginPage()), (Route<dynamic> route) => false); }, child: Text("Log Out", style: TextStyle(color: Colors.white)), ), ], ), body: Center(child: Text("Main Page")), drawer: Drawer(), ); } }
内容的提问来源于stack exchange,提问作者Napoleon Wai Lun Wong
相关产品推荐
相关产品推荐

