Flutter首次启动SharedPreferences初始值为null的处理方案
两种方案的优劣对比
- 方案1(逐处判空):完全不推荐。这种写法会产生大量重复冗余代码,后续如果需要调整默认值,必须遍历所有调用位置修改,只要漏改一处就会出现逻辑异常,维护成本极高。
- 方案2(启动预写默认值):比方案1合理,能避免业务层反复判空,但存在两个明显缺陷:一是启动阶段需要对所有空配置执行写入操作,会产生不必要的本地IO开销;二是每新增一个配置项就要修改初始化方法,配置项多了之后初始化方法会变得臃肿难维护,后续版本迭代如果修改默认值,已经写入过旧默认值的老用户无法自动生效,还要额外写兼容逻辑。
更优的落地方式
最推荐的做法是对SharedPreferences做统一封装收口,把默认值配置、读写逻辑全部收敛到单一工具类中,既不需要提前写入默认值,也不需要业务层做判空处理。
具体实现参考:
- 先编写统一的SP工具类,所有配置的key、默认值、读写方法全在这个类里维护:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class SpUtil { static late final SharedPreferences _instance; // 统一维护配置key和对应默认值,新增/修改配置只需要改这里 static const _kThemeColorKey = "color"; static const _defaultThemeColorValue = Colors.white.value; // 应用启动时调用一次完成初始化 static Future<void> init() async { _instance = await SharedPreferences.getInstance(); } // 对外提供非空的主题色取值,业务层直接调用即可,不需要判空 static Color get themeColor { final storedValue = _instance.getInt(_kThemeColorKey); return Color(storedValue ?? _defaultThemeColorValue); } // 对外提供主题色写入方法 static Future<void> updateThemeColor(Color newColor) async { await _instance.setInt(_kThemeColorKey, newColor.value); } // 如果配置项多,可以补充通用类型的读写方法减少重复代码 static int getInt(String key, int defaultValue) { return _instance.getInt(key) ?? defaultValue; } static Future<bool> setInt(String key, int value) { return _instance.setInt(key, value); } // 其他String、bool、double类型的通用方法可以按相同逻辑补充 }
- 启动应用时先完成工具类初始化,再挂载根组件:
void main() async { // 保证插件绑定初始化 WidgetsFlutterBinding.ensureInitialized(); // 初始化SP工具 await SpUtil.init(); runApp(const MyApp()); }
- 业务层使用时直接调用工具类拿值即可,不需要任何判空逻辑:
// 直接取值用,不会出现null问题 @override Widget build(BuildContext context) { return Container( color: SpUtil.themeColor, ); }
这个方案的优势很明显:
- 没有冗余的判空代码,业务层调用非常简洁
- 所有配置集中维护,改默认值、加新配置不需要翻业务代码,不会出现漏改问题
- 不需要启动时提前写入默认值,减少了不必要的本地IO,对启动速度更友好
- 后续如果需要做配置迁移(比如版本更新调整默认配置),只需要在工具类的init方法里加对应逻辑即可,维护成本极低
内容的提问来源于stack exchange,提问作者Coder
相关产品推荐
相关产品推荐

