Flutter使用injectable与get_it时抽象类注册及环境切换异常问题
核心问题前置结论
绝对不要给抽象类/抽象接口添加@injectable或@Injectable注解。这类注解仅用于标注可直接实例化的具体实现类,给抽象类加注解触发"抽象类无法直接注册"报错是必然结果。
问题1:抽象仓储依赖未注册报错修复
报错根因:@injectable 注解默认会将被标注的类注册为自身类型,不会自动绑定到类实现的抽象接口/父类。你之前仅给两个仓储实现类加了基础@injectable注解,实际注册到容器里的是DevRandomQuantityRepository、ProdRandomQuantityRepository两个具体类型,Bloc依赖的IRandomQuantityRepository抽象类型没有对应注册项,自然触发未注册报错。
正确配置方式:给两个具体仓储实现类添加类型绑定参数,明确声明该实现是对应抽象类的注入实例,示例代码如下:
// 开发环境仓储实现 @dev @Injectable(as: IRandomQuantityRepository) class DevRandomQuantityRepository implements IRandomQuantityRepository { // 开发环境业务逻辑 } // 生产环境仓储实现 @prod @Injectable(as: IRandomQuantityRepository) class ProdRandomQuantityRepository implements IRandomQuantityRepository { // 生产环境业务逻辑 }
注意:绑定抽象类型必须使用大写开头的
@Injectable()注解传入as参数,小写的@injectable是默认无参的快捷写法,不支持类型绑定配置。
问题2:环境切换失效修复
传Env.dev仍拿到生产环境实现,90%的情况是以下两个原因导致:
- 初始化方法未透传环境参数
检查injection.dart的初始化配置,必须将调用方传入的环境参数传给生成的初始化方法,正确配置参考:// 环境常量,字符串值必须和内置@dev、@prod注解的默认值完全匹配 abstract class Env { static const dev = 'dev'; static const prod = 'prod'; } final getIt = GetIt.instance; @InjectableInit( initializerName: 'configureInjection', preferRelativeImports: true, asExtension: false, ) Future<void> configureInjection(String environment) async { // 必须给生成的$initGetIt方法传入environment参数,否则环境配置不生效 await $initGetIt(getIt, environment: environment); } - 环境常量值不匹配
injectable内置的@dev注解默认匹配的环境字符串是dev,@prod默认匹配prod,如果自定义的Env常量值写成development/production这类不匹配的字符串,框架找不到对应环境的实现,会默认加载最后扫描到的实现类,也就是你遇到的默认加载生产实现的问题。
Bloc层配置校验
业务层RandomQuantityBloc不需要额外配置,正常加@injectable注解即可,框架会自动识别构造函数中的抽象依赖,匹配当前环境下绑定的实现类注入:
@injectable class RandomQuantityBloc extends Bloc<RandomQuantityEvent, RandomQuantityState> { final IRandomQuantityRepository repository; RandomQuantityBloc(this.repository); }
最后重新生成代码
删掉之前给IRandomQuantityRepository抽象类加的所有injectable相关注解,执行以下命令清理旧的无效生成代码、重新生成注入配置:flutter pub run build_runner build --delete-conflicting-outputs
生成完成后可以通过打印注入实例的runtimeType校验配置是否生效:print(getIt<IRandomQuantityRepository>().runtimeType);
开发环境下输出DevRandomQuantityRepository即为配置正确。
内容的提问来源于stack exchange,提问作者MetaStack

