如何使用Riverpod完成SharedPreferences依赖注入
你的问题核心是 SharedPreferences.getInstance() 返回的是 Future<SharedPreferences>,而你直接将异步返回的 Future 注入给了需要同步获取实例的数据源,导致类型不匹配。推荐以下两种方案,优先选择第一种预初始化方案。
方案一:启动前预初始化(首推)
SharedPreferences 初始化速度极快,提前在应用启动前完成初始化,后续所有依赖都可以同步获取实例,无需处理异步状态。
步骤1:修改 main 函数完成预初始化
void main() async { // 确保 Flutter 插件初始化完成,否则无法调用 SharedPreferences 原生方法 WidgetsFlutterBinding.ensureInitialized(); // 同步等待 SharedPreferences 实例初始化完成 final sharedPreferences = await SharedPreferences.getInstance(); runApp( ProviderScope( overrides: [ // 将初始化完成的实例覆盖注入到 provider 中 sharedPreferencesProvider.overrideWithValue(sharedPreferences), ], child: const MyApp(), ), ); }
步骤2:修改 sharedPreferencesProvider 定义
// 声明返回 SharedPreferences 实例,默认实现抛出异常避免未覆盖的情况被误用 final sharedPreferencesProvider = Provider<SharedPreferences>((ref) { throw UnimplementedError('sharedPreferencesProvider 需在启动时通过 overrideWithValue 注入实例'); });
修改后你原本的其他 provider 不需要做任何调整,直接 ref.watch(sharedPreferencesProvider) 就可以拿到可用的 SharedPreferences 实例。
方案二:异步加载适配
如果不想阻塞应用启动,也可以将整条依赖链适配为异步处理:
步骤1:将 sharedPreferencesProvider 改为 FutureProvider
final sharedPreferencesProvider = FutureProvider<SharedPreferences>((ref) async { return await SharedPreferences.getInstance(); });
步骤2:调整依赖的 provider 适配异步
所有依赖 sharedPreferencesProvider 的 provider 都需要改为异步实现,例如本地数据源 provider:
final _localDataSourceProvider = FutureProvider<ItemLocalDataSource>((ref) async { // 等待 SharedPreferences 实例初始化完成 final prefs = await ref.watch(sharedPreferencesProvider.future); return ItemLocalDataSourceImpl(sharedPreferences: prefs); });
后续依赖该数据源的 repository、use case、状态管理器都需要对应处理 AsyncValue 的 loading、error 状态,适合初始化耗时较长的依赖,不推荐给 SharedPreferences 使用。
内容的提问来源于stack exchange,提问作者Vincent Gagnon
相关产品推荐
相关产品推荐

