如何实现带初始化逻辑的Dart单例类?以SharedPreference服务为例
实现说明
需要同时满足两个要求:
- 类全局唯一实例(单例)
- 确保
_prefs实例初始化完成后才会被方法调用,避免LateInitializationError
方案1:启动预初始化(推荐,性能更优)
提前在应用启动阶段完成初始化,后续调用无异步等待开销。
封装代码
import 'package:shared_preferences/shared_preferences.dart'; class SharedPreferenceService { // 静态单例实例 static late final SharedPreferenceService _instance; // 初始化完成的SharedPreferences实例 late final SharedPreferences _prefs; // 私有构造函数,禁止外部手动实例化 SharedPreferenceService._(); /// 初始化方法,必须在main函数runApp前调用 static Future<SharedPreferenceService> init() async { _instance = SharedPreferenceService._(); _instance._prefs = await SharedPreferences.getInstance(); return _instance; } /// 对外获取单例的入口 static SharedPreferenceService get instance => _instance; // 原有业务方法 Future<void> setIntroPagesHaveBeenViewed() async { await _prefs.setBool(SharedPreferenceKey.INTRODUCTION_PAGES_HAVE_BEEN_VIEWED, true); } Future<bool> checkIfIntroPagesHaveBeenViewed() async { return _prefs.getBool(SharedPreferenceKey.INTRODUCTION_PAGES_HAVE_BEEN_VIEWED) ?? false; } }
使用方式
在项目入口main函数中提前初始化:
void main() async { // 确保Flutter框架绑定已初始化 WidgetsFlutterBinding.ensureInitialized(); // 等待SharedPreference单例初始化完成 await SharedPreferenceService.init(); runApp(const MyApp()); }
业务代码中直接调用:
// 存储状态 await SharedPreferenceService.instance.setIntroPagesHaveBeenViewed(); // 读取状态 bool hasViewed = await SharedPreferenceService.instance.checkIfIntroPagesHaveBeenViewed();
方案2:懒加载初始化
无需提前初始化,第一次使用时自动完成初始化,适合对启动速度要求极高的场景。
封装代码
import 'package:shared_preferences/shared_preferences.dart'; import 'dart:async'; class SharedPreferenceService { // 静态单例实例 static final SharedPreferenceService _instance = SharedPreferenceService._internal(); // 用于等待SharedPreferences初始化完成的Completer final Completer<SharedPreferences> _prefsCompleter = Completer<SharedPreferences>(); // 工厂构造函数,对外返回唯一实例 factory SharedPreferenceService() { return _instance; } // 内部私有构造 SharedPreferenceService._internal() { _initPrefs(); } // 异步初始化SharedPreferences void _initPrefs() async { final prefs = await SharedPreferences.getInstance(); _prefsCompleter.complete(prefs); } // 原有业务方法,内部自动等待初始化完成 Future<void> setIntroPagesHaveBeenViewed() async { final prefs = await _prefsCompleter.future; await prefs.setBool(SharedPreferenceKey.INTRODUCTION_PAGES_HAVE_BEEN_VIEWED, true); } Future<bool> checkIfIntroPagesHaveBeenViewed() async { final prefs = await _prefsCompleter.future; return prefs.getBool(SharedPreferenceKey.INTRODUCTION_PAGES_HAVE_BEEN_VIEWED) ?? false; } }
使用方式
无需提前初始化,业务代码直接调用即可:
// 存储状态 await SharedPreferenceService().setIntroPagesHaveBeenViewed(); // 读取状态 bool hasViewed = await SharedPreferenceService().checkIfIntroPagesHaveBeenViewed();
内容的提问来源于stack exchange,提问作者Agung
相关产品推荐
相关产品推荐

