You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Injectable+Get_it集成SharedPreferences报错及解决方法

如何正确结合Injectable与SharedPreferences解决未就绪实例问题?

这个报错我之前也遇到过!核心问题是SharedPreferences.getInstance()是异步操作,但你同步获取LoginCheckBloc时,它依赖的SharedPref所需要的SharedPreferences实例还没完成初始化。Injectable处理异步依赖需要特殊配置,下面是完整的解决步骤:

1. 标记异步依赖为预解析

修改你的InjectableModule,给SharedPreferences的getter添加@preResolve注解,告诉Injectable在初始化阶段先等待这个异步操作完成:

@module
abstract class InjectableModule {
  @preResolve // 新增这个注解
  @lazySingleton
  Future<SharedPreferences> get prefs => SharedPreferences.getInstance();
}

2. 异步初始化GetIt依赖

在main函数中,需要异步等待所有预解析的依赖完成初始化,再启动App:

void main() async {
  // 必须确保Flutter绑定先初始化
  WidgetsFlutterBinding.ensureInitialized();
  // 异步等待依赖配置完成(Injectable生成的代码会处理@preResolve的依赖)
  await configureDependencies();
  runApp(MyApp());
}

注意:当你使用@preResolve后,Injectable生成的configureDependencies()会变成异步函数,所以必须用await等待它完成。

3. 保持SharedPref与LoginCheckBloc的代码不变

你的SharedPref和LoginCheckBloc的依赖注入逻辑是正确的,不需要修改:

@LazySingleton()
class SharedPref {
  final String _token = 'token';
  final SharedPreferences _pref;
  SharedPref(this._pref);

  Future<String> getToken() async {
    return _pref.getString(_token) ?? '';
  }

  Future<void> setToken(String token) async {
    await _pref.setString(_token, token);
  }
}
@injectable
class LoginCheckBloc extends Bloc<LoginCheckEvent, LoginCheckState> {
  final SharedPref sharedPref;
  LoginCheckBloc({@required this.sharedPref}) : super(const LoginCheckState.initial());

  @override
  Stream<LoginCheckState> mapEventToState(LoginCheckEvent event) async* {
    if (event is CheckLogin) {
      final String token = await sharedPref.getToken();
      yield token.isEmpty 
          ? const LoginCheckState.notLogin() 
          : const LoginCheckState.successLogin();
    }
  }
}

4. 正常获取LoginCheckBloc实例

现在所有异步依赖都已经在初始化阶段完成了,你原来的获取方式就不会再报错:

BlocProvider<LoginCheckBloc>(
  create: (BuildContext context) => getIt<LoginCheckBloc>()..add(CheckLogin()),
)

额外说明

@preResolve的作用是让Injectable在初始化GetIt时,优先等待被标记的异步依赖完成,将结果存入GetIt容器。这样后续获取依赖时,拿到的就是已经就绪的实例,而不是未完成的Future。如果有多个异步依赖,都可以用@preResolve标记,configureDependencies()会自动等待所有它们完成。

内容的提问来源于stack exchange,提问作者ali hoseinpoor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:07:31