Flutter中Hive单例结合Riverpod使用时Getter返回Null问题求助
解决Hive单例初始化与Riverpod集成的空值问题
问题根源
- 单例初始化逻辑错误:
Takok类的akses()方法里创建了新的Takok._internal()实例,而非使用已有的全局单例_t,导致真正完成初始化的是临时实例,全局单例的_boxTransaksi和_boxInappProses始终为null。 - Riverpod Provider未处理异步初始化:
providerTakok直接返回未初始化的Takok实例,此时调用boxInappProsesgetter会触发空值检查错误,因为异步初始化操作还未执行完成。
修复步骤
1. 修正Takok单例的初始化逻辑
修改akses()方法,确保操作的是全局单例本身,同时添加初始化标记避免重复执行:
class Takok { static final Takok _t = Takok._internal(); factory Takok() => _t; Takok._internal(); Box<Transaksi>? _boxTransaksi; Box<InappProses>? _boxInappProses; bool _isInitialized = false; // 标记是否已完成初始化 Future<Takok> akses() async { if (_isInitialized) return this; // 已初始化直接返回 final direktori = await getApplicationDocumentsDirectory(); await Hive.initFlutter(direktori.path); await init(); _isInitialized = true; return this; } Future<void> init() async { Hive.registerAdapter(TransaksiAdapter()); Hive.registerAdapter(InappProsesAdapter()); _boxTransaksi = await Hive.openBox<Transaksi>('transaksi'); _boxInappProses = await Hive.openBox<InappProses>('inappproses'); } Box<Transaksi> get boxTransaksi => _boxTransaksi!; Box<InappProses> get boxInappProses => _boxInappProses!; }
2. 用Riverpod FutureProvider提供已初始化的Takok实例
由于初始化是异步操作,使用FutureProvider确保只有初始化完成后才对外提供可用实例:
final providerTakok = FutureProvider<Takok>((ref) async { return await Takok().akses(); });
3. 调整TakokHelper的Provider,依赖已初始化的Takok
使用ChangeNotifierProvider.async处理异步依赖,确保获取的是已完成初始化的Takok实例:
final providerTakokHelper = ChangeNotifierProvider.async<TakokHelper>((ref) async { final db = await ref.watch(providerTakok.future); return TakokHelper(db, db.boxInappProses); });
4. 修正Splash屏幕的Provider使用方式
针对异步Provider,需通过.future等待初始化完成后再执行逻辑:
final providerSplashskrin = Provider((ref) { Future.delayed(const Duration(seconds: 3), () async { try { final takokHelper = await ref.watch(providerTakokHelper.future); print('objection'); // 后续业务逻辑 } catch (e) { print('error: $e'); } }); });
内容的提问来源于stack exchange,提问作者pras
相关产品推荐
相关产品推荐

