Search code examples
flutterpackagecode-generation

Flutter Injectable factory not registered error


I'm having an issue while using the Injectable package for Flutter: https://pub.dev/packages/injectable

I'm getting an error telling me that I don't have a factory registered, but I'm trying to get it

This is the class I'm trying to get but as you can see it's annotated with @injectable

auth_bloc.dart

import 'package:freezed_annotation/freezed_annotation.dart';

@injectable
class AuthBloc extends Bloc<AuthEvent, AuthState> {

}

Also in the injection.config.dart you can clearly see that the AuthBloc has it's factory defined

Future<GetIt> $initGetIt(
  GetIt get, {
  String environment,
  EnvironmentFilter environmentFilter,
}) async {
  final gh = GetItHelper(get, environment, environmentFilter);

  ...

  gh.factory<AuthBloc>(() => AuthBloc(get<IAuthRepository>()));

  ...

  return get;
}

This is my main.dart

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  configureInjection(Environment.dev);
  runApp(MyApp());
}

Here is where I'm trying to getIt

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider<AuthBloc>(
          create: (context) {
            return getIt<AuthBloc>() // <============ HERE
              ..add(
                const AuthEvent.authCheckRequested(), 
              );
          },
        ),
      ],
      child: MaterialApp(
         ...
      ),
    );
  }
}

This is the injection.dart file

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

final GetIt getIt = GetIt.instance;

@injectableInit
void configureInjection(String env) {
  $initGetIt(getIt, environment: env);
}

This is the error message I'm getting

Object/factory with  type AuthBloc 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?)
'package:get_it/get_it_impl.dart':
Failed assertion: line 298 pos 9: 'instanceFactory != null'

These are my pubspeck.yaml dependencies

...
dependencies:
  injectable: ^1.0.5
...
dev_dependencies:
  injectable_generator: ^1.0.6
...

Solution

  • I finally solved my issue. The problem was that I was not waiting for the getIt initialization to complete before I called the getIt() function. So it tried to get something that was not yet initialized.

    The getIt initialization was not a synchronous function because one of my @modules was asynchronous. Specifically, the SharedPreferences package, which constructor is asynchronous (Future<SharedPreferences> getInstance()). So if you have a module that is asynchronous then you need to await the configureInjection() function

    To solve the problem you just have to await the getIt initialization in your main.dart

    I had to change my main.dart code:

    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp();
      // From this
      // configureInjection(Environment.dev);
      // to this:
      await configureInjection(Environment.dev);
      runApp(MyApp());
    }
    

    Make sure your configureInjection returns a Future Future<void> configureInjection(String env)

    If you are using the Injectable package, you will need to annotate your @module or injectable with @preResolve, so the module is awaited in the configureInjection function. Like so:

    @preResolve
    Future<SharedPreferences> get sharedPreferences => SharedPreferences.getInstance();