flutterfirebasedependency-injectionflutter-dependenciesinjectable

Flutter Injectable - Object/factory with type xxxxx is not registered inside GetIt


Im trying to use flutter plugin 'Injectable' but i got this error.

This error keeps coming even after having tried all the possible solutions provided in other questions

he following assertion was thrown building SignInPage(dirty, state: _SignInPageState#16126):
                    Object/factory with  type FirebaseAuthRepository 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 372 pos 7: 'instanceFactory != null'

the dependency injection config :

as you can see down below, i was confused with the error because the FirebaseAuthRepository have already registered inside the injection config

const String _prod = 'prod';

// ignore_for_file: unnecessary_lambdas
// ignore_for_file: lines_longer_than_80_chars
// initializes the registration of main-scope dependencies inside of GetIt
_i1.GetIt init(
  _i1.GetIt getIt, {
  String? environment,
  _i2.EnvironmentFilter? environmentFilter,
}) {
  final gh = _i2.GetItHelper(
    getIt,
    environment,
    environmentFilter,
  );
  final registerModul = _$RegisterModul();
  gh.lazySingleton<_i3.FirebaseAuth>(() => registerModul.firebaseAuth);
  gh.lazySingleton<_i4.FirebaseAuthRepositoryImpl>(
    () => _i4.FirebaseAuthRepositoryImpl(
        remoteDataSource: gh<_i5.FirebaseAuthenticationRemoteDataSource>()),
    registerFor: {_prod},
  );
  gh.lazySingleton<_i6.FirebaseAuthResetPassword>(
    () => _i6.FirebaseAuthResetPassword(
        repository: gh<_i7.FirebaseAuthRepository>()),
    registerFor: {_prod},
  );
  gh.lazySingleton<_i8.FirebaseAuthSignIn>(
    () => _i8.FirebaseAuthSignIn(repository: gh<_i7.FirebaseAuthRepository>()),
    registerFor: {_prod},
  );
  gh.lazySingleton<_i9.FirebaseAuthSignOut>(
    () => _i9.FirebaseAuthSignOut(repository: gh<_i7.FirebaseAuthRepository>()),
    registerFor: {_prod},
  );
  gh.lazySingleton<_i10.FirebaseAuthSignUp>(
    () => _i10.FirebaseAuthSignUp(repository: gh<_i7.FirebaseAuthRepository>()),
    registerFor: {_prod},
  );
  gh.lazySingleton<_i5.FirebaseAuthenticationRemoteDataSourceImpl>(
    () => _i5.FirebaseAuthenticationRemoteDataSourceImpl(
        firebaseAuth: gh<_i3.FirebaseAuth>()),
    registerFor: {_prod},
  );
  gh.factory<_i11.FirebaseAuthNotifier>(() => _i11.FirebaseAuthNotifier(
        firebaseAuthSignUp: gh<_i10.FirebaseAuthSignUp>(),
        firebaseAuthSignIn: gh<_i8.FirebaseAuthSignIn>(),
        firebaseAuthSignOut: gh<_i9.FirebaseAuthSignOut>(),
        firebaseAuthResetPassword: gh<_i6.FirebaseAuthResetPassword>(),
      ));
  return getIt;
}

class _$RegisterModul extends _i12.RegisterModul {}

the problem file :

this is the file mentioned in the debug console

abstract class FirebaseAuthRepository {
  Future<Either<Failure, UserCredential>> authSignInEmailPassword(String email, String password);
  Future<Either<Failure, UserCredential>> authSignUpEmailPassword(String email, String password);
  Future<Either<Failure, void>> resetPassword(String email);
  Future<Either<Failure, void>> authSignOut();
}

@prod
@lazySingleton
@Injectable(as: FirebaseAuthRepository)
class FirebaseAuthRepositoryImpl extends FirebaseAuthRepository {

  final FirebaseAuthenticationRemoteDataSource remoteDataSource;

  FirebaseAuthRepositoryImpl({
    required this.remoteDataSource
  });

  @override
  Future<Either<Failure, UserCredential>> authSignInEmailPassword(String email, String password) async {
    try {
      final result = await remoteDataSource.authSignInEmailPassword(email, password);
      return Right(result);
    } on SocketException {
      return Left(ConnectionFailure('Failed to connect to network'));
    } on FirebaseAuthException catch (e) {
      if (kDebugMode) {
        print('Failed with error code: ${e.code}');
        return Left(FirebaseFailure('Failed with error code: ${e.code}'));
      }
      if (e.code == 'user-not-found') {
        return Left(FirebaseFailure('No user found for that email'));
      }
      if (e.code == 'wrong-password') {
        return Left(FirebaseFailure('Wrong password provided for that user'));
      }
      return Left(FirebaseFailure('Failed with error code: ${e.code}'));
    }
  }

  @override
  Future<Either<Failure, void>> authSignOut() async {
    try {
      final result = await remoteDataSource.authSignOut();
      return Right(result);
    } on SocketException {
      return Left(ConnectionFailure('Failed to connect to network'));
    } on FirebaseAuthException catch (e) {
      if (kDebugMode) {
        print('Failed with error code: ${e.code}');
      }
      return Left(FirebaseFailure('Failed with error code: ${e.code}'));
    }
  }

  @override
  Future<Either<Failure, UserCredential>> authSignUpEmailPassword(String email, String password) async {
    try {
      final result = await remoteDataSource.authSignInEmailPassword(email, password);
      return Right(result);
    } on SocketException {
      return Left(ConnectionFailure('Failed to connect to network'));
    } on FirebaseAuthException catch (e) {
      if (kDebugMode) {
        print('Failed with error code: ${e.code}');
        return Left(FirebaseFailure('Failed with error code: ${e.code}'));
      }
      if (e.code == 'weak-password') {
        return Left(FirebaseFailure('The password provided is too weak'));
      }
      if (e.code == 'email-already-in-use') {
        return Left(FirebaseFailure('The account already exists for that email'));
      }
      return Left(FirebaseFailure('Failed with error code: ${e.code}'));
    }
  }

  @override
  Future<Either<Failure, void>> resetPassword(String email) async {
   try {
    final result = await remoteDataSource.resetPassword(email);
    return Right(result);
   } on SocketException {
      return Left(ConnectionFailure('Failed to connect to network'));
    } on FirebaseAuthException catch (e) {
      if (kDebugMode) {
        print('Failed with error code: ${e.code}');
      }
      return Left(FirebaseFailure('Failed with error code: ${e.code}'));
    }
  }
  
}

i tried injecting the abstract class but it won't work, instead i got another error

@injectable
abstract class FirebaseAuthRepository {
  Future<Either<Failure, UserCredential>> authSignInEmailPassword(String email, String password);
  Future<Either<Failure, UserCredential>> authSignUpEmailPassword(String email, String password);
  Future<Either<Failure, void>> resetPassword(String email);
  Future<Either<Failure, void>> authSignOut();
}

Solution

  • You should use either of one annotation @injectable or lazySingleton, You should not use two annotation for single instance Injectable, both represents the same.

    @prod
    @LazySingleton(as: FirebaseAuthRepository)
    

    Or

    @prod
    @Injectable(as: FirebaseAuthRepository)
    

    You should decide, which one is suitable for this.

    In Additional, FYI: you can also use env parameter in annotation to decide the environment

    @LazySingleton(as: FirebaseAuthRepository, env: ['prod'])