Flutter如何在App加载前完成SharedPreferences初始化 避免Instance of Future提示
问题原因
- 你直接在build的三元表达式中返回异步方法
createSharedObject(),该方法返回的是Future对象,未等待执行完成就转为字符串显示,就会出现Instance of Future提示。 - 你在main函数、MyApp的build方法中手动创建
_MyHomePageState实例调用初始化方法是无效的,手动创建的State和页面实际挂载的State不是同一个实例,初始化的sp对象不会同步到页面的State中。
修复方案
步骤1:在main函数提前完成sp初始化
Flutter支持main方法异步,直接在启动app前等待sp初始化完成:
void main() async { WidgetsFlutterBinding.ensureInitialized(); // 等待sp初始化完成再启动app final SharedPreferences sp = await SharedPreferences.getInstance(); runApp(MyApp(sp: sp)); }
注意SharedPreferences.getInstance()是全局单例,初始化一次之后后续所有调用返回的都是同一个实例
步骤2:逐层透传sp实例到使用页面
修改MyApp接收初始化好的sp,再传递给首页:
class MyApp extends StatelessWidget { final SharedPreferences sp; const MyApp({super.key, required this.sp}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter Demo', theme: ThemeData(primarySwatch: Colors.blue), home: MyHomePage(sp: sp), ); } }
步骤3:改造首页代码,删除多余的初始化逻辑
class MyHomePage extends StatefulWidget { final SharedPreferences sp; const MyHomePage({super.key, required this.sp}); @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { String? baslik, mesaj; List<String> kaydedilenNotlar = []; List<String> kaydedilenBasliklar = []; late SharedPreferences sharedPreferences; @override void initState() { super.initState(); // 直接取透传过来的实例,无需再异步初始化 sharedPreferences = widget.sp; // 可以直接读取本地存储的数据 kaydedilenNotlar = sharedPreferences.getStringList("not") ?? []; kaydedilenBasliklar = sharedPreferences.getStringList("baslik") ?? []; } // 原有createSharedObject方法可以直接删除
步骤4:修改build中的展示逻辑
删除build中调用异步初始化方法的代码,直接读取sp内容:
body: TabBarView( children: [ Center(child: Text("${kaydedilenNotlar}")), Center(child: Text("2. sayfa")), Center(child: Text("3. sayfa")), ], ),
补充优化建议
- 点击保存按钮调用setStringList之后,调用
setState((){})刷新页面,新保存的内容就会实时更新。 - 如果项目页面较多,不想逐层传递sp实例,可以使用get_it等依赖注入工具将sp注册为全局单例,使用时直接获取即可。
内容的提问来源于stack exchange,提问作者yesf
相关产品推荐
相关产品推荐

