Flutter中从SharedPreferences读取名称显示null的解决方法
问题根源
- 异步执行顺序错误:
initState中同步调用fetchName()、storeName()、getStoreName(),但fetchName()是异步获取Firestore数据,此时user?.displayName可能还未加载完成,导致存储的是null。 - 未等待异步读取完成:
getStoreName()中调用getNameFromSharedPreferences()时没有用await,直接打印displayName,此时SharedPreferences的读取操作还没完成,值还未赋值给_displayName。 - 未触发UI更新:即使成功读取到用户名,也没有调用
setState()通知Flutter重建UI,导致界面无法显示最新值。
修正后的代码实现
1. 调整首页的初始化逻辑
统一处理异步流程,确保Firestore数据加载完成后再执行存储和读取操作:
@override void initState() { super.initState(); _initData(); // 统一管理异步初始化步骤 } // 串行执行异步操作,保证顺序 Future<void> _initData() async { await getData(); await fetchName(); // 等待Firestore用户名加载完成 await storeName(); // 确保user已存在再存储 await getStoreName(); // 等待读取完成并更新UI } Future<void> getStoreName() async { await getNameFromSharedPreferences(); // 等待SharedPreferences读取完成 setState(() {}); // 触发UI重建 print("name $displayName"); } Future<void> storeName() async { if (user?.displayName != null) { // 先判断用户名是否存在 String displayName = user!.displayName!; await saveNameToSharedPreferences(displayName); // 存储操作也需等待完成 } }
2. 优化SharedPreferences工具类
移除全局变量,改为直接返回读取结果,避免全局状态混乱:
import 'package:shared_preferences/shared_preferences.dart'; Future<void> saveNameToSharedPreferences(String displayName) async { final SharedPreferences sn = await SharedPreferences.getInstance(); await sn.setString('displayName', displayName); } Future<String?> getNameFromSharedPreferences() async { final SharedPreferences sn = await SharedPreferences.getInstance(); return sn.getString('displayName'); // 直接返回读取到的用户名 }
3. 页面内维护状态并显示用户名
在页面内部维护本地状态,读取完成后更新UI:
// 页面内部声明状态变量 String? _localDisplayName; // 修改getStoreName方法 Future<void> getStoreName() async { _localDisplayName = await getNameFromSharedPreferences(); setState(() {}); // 通知UI更新 print("name $_localDisplayName"); } // 在build方法中展示用户名 @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Text(_localDisplayName ?? "未获取到用户名"), ), ); }
内容的提问来源于stack exchange,提问作者Dasun Dola
相关产品推荐
相关产品推荐

