Milad-Akarie / injectable

Code Generator for get_it
MIT License
565 stars 143 forks source link

Issue with Auto-generated Code Using @injectableInit - Bad State Error with GetIt Dependency Injection #466

Open ShiyanaSam opened 6 months ago

ShiyanaSam commented 6 months ago

After upgrading to Flutter 3.22.0, injectable auto generated code gives following exception

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Bad state: GetIt: Object/factory with type BuildConfig is not registered inside GetIt. (Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;

injection.dart file

import 'package:get_it/get_it.dart'; import 'package:injectable/injectable.dart'; import 'package:testapp/injection.config.dart';

final GetIt getIt = GetIt.instance;

@InjectableInit() void configureInjection(String env) { getIt.init(environment: env);

}

..............................

@Injectable(as: BuildConfig, env: [Environment.dev]) class BuildConfigDev extends BuildConfig { @override String get baseUrl => secrets.baseDevUrl;

@override Future configure(Locale? locale) async => runApp( MyApp( locale: locale, ), ); }

...............................

injectable_api_module.dart file

@module abstract class InjectableApiModule { @singleton UserApi get userApi => UserApi( NetworkService.dio, baseUrl: getIt().baseUrl, //this is where the exception occurs when running the app );

}

KarinBerg commented 5 months ago

@ShiyanaSam Which version of "injectable_generator" do you use? If it is 2.6.1 try downgrading to 2.6.0 and tell me if it is working again.

I had a similar issue with the exception:

StateError (Bad state: GetIt: Object/factory with type AppEnv is not registered inside GetIt. 
(Did you accidentally do GetIt sl=GetIt.instance(); instead of GetIt sl=GetIt.instance;
Did you forget to register it?))

My workaround solution: I only changed the version of injectable_generator from 2.6.1 back to 2.6.0 and it is working again.

Source of the issue: For me it seems that the PR https://github.com/Milad-Akarie/injectable/pull/438 (the only change in version 2.6.1) seems to cause the issue. My order of the registered classes changed which leads to a missing object state error from above for the type "AppEnv" which is now registered after the first use.

With v2.6.0 it is:

_i1.GetIt init({
    String? environment,
    _i2.EnvironmentFilter? environmentFilter,
  }) {
    final gh = _i2.GetItHelper(
      this,
      environment,
      environmentFilter,
    );
    final configModule = _$ConfigModule();
    final serviceModule = _$ServiceModule();
    gh.singleton<_i3.AppEnv>(
      () => configModule.prodEnv,
      registerFor: {_prod},
    );
    gh.singleton<_i3.AppEnv>(
      () => configModule.devEnv,
      registerFor: {_dev},
    );
    gh.singleton< ...
    gh.singleton< ...
    ...
}

In v2.6.1 it is:

_i1.GetIt init({
    String? environment,
    _i2.EnvironmentFilter? environmentFilter,
  }) {
    final gh = _i2.GetItHelper(
      this,
      environment,
      environmentFilter,
    );
    final configModule = _$ConfigModule();
    final serviceModule = _$ServiceModule();
    ...
    gh.singleton< ...
    gh.singleton< ...
    ...
    gh.singleton<_i3.AppEnv>(
      () => configModule.devEnv,
      registerFor: {_dev},
    );
    ...
   gh.singleton< ...
   gh.singleton< ...
   gh.singleton< ...
   gh.singleton< ...
   ...
   gh.singleton<_i3.AppEnv>(
      () => configModule.prodEnv,
      registerFor: {_prod},
    );

@Adam-Langley: Do you have any idea what can cause this wrong registration order after your PR? It could be related to the "registerFor" argument. But I'm pretty new to this code generating stuff 🙂.

Adam-Langley commented 5 months ago

Hi @KarinBerg, @ShiyanaSam would either of you be able to provide a minimal reproduction project?

Thanks,

KarinBerg commented 5 months ago

I check if I can create a small sample with my problem.

KarinBerg commented 5 months ago

ok, I managed to create a small example. You can download the project here: Link.

This example contains two launch configurations which starting the app via two different main functions and in theory with different environment configurations. One to start the app with "PROD" environment and one for the "DEV" (notice that this is just simulated here. I do not pass any config file in this example). The example uses flutter 3.19.3 in case this is relevant. You can use the generateApp.sh script to fetch all dependencies and run the builder like I do. I used an iOS simulator as a target device.

To get the StateError "Bad state: GetIt: Object/factory with type AppEnv is not registered inside GetIt." you have to use the version 2.6.1 of the injectable_generator and start the app via the main_prod.dart launch configuration. The StateError is not thrown if you start the app via the main_dev.dart launch configuration.

The StateError is also not thrown if you use the version 2.6.0 of the injectable_generator and starting the app via any launch configuration.

What I also notice while creating this example is, if I move the file "app_env.dart" from "lib/core" to "lib", using injectable_generator:2.6.1 and rerun the builder then the StateError is also not thrown. Unfortunatelly this change does not fix the problem in my real flutter project. But I wanted to mention it. Maybe it is a hint for you :).

I hope this helps you to find the problem. I you need any info then please let me know. Thanks for your time and help, Karin

KarinBerg commented 2 months ago

@Adam-Langley Do you have some time to check my example project and the issue?

gj-thaoht commented 4 weeks ago

Hi @KarinBerg, @ShiyanaSam would either of you be able to provide a minimal reproduction project?

Thanks,

I find the topic 477 resolves issues the same.

KarinBerg commented 4 weeks ago

I can confirm that https://github.com/Milad-Akarie/injectable/pull/477 is resolving my issue, too.

I updated my example project from above: Link

KarinBerg commented 4 weeks ago

@Milad-Akarie Would be awesome if you could review the https://github.com/Milad-Akarie/injectable/pull/477 🤩