Search code examples
flutterdependency-injectionsharedpreferencesinjectable

Flutter dependency injenction with shared preferences


Good evening, I'm trying to use dependency injection with the shared preferences plugin, but as soon is I generate the code, I get an error for an unrelated Bloc. I use

  • GetIt: ^0.5.3,
  • injectable_generator: 1.0.6
  • flutter_bloc: ^6.1.1.

My Goal is to inject SharedPreferences into a class for handling local operations, it looks like that:

class LocalSharedPreferences {
 final SharedPreferences _preferences;

 LocalSharedPreferences(this._preferences);
 ...
}

In order to inject SharedPreferences properly, I followed its official documentation (https://pub.dev/packages/injectable#registering-asynchronous-injectables), thus my code to inject a 3rd-party module looks like this:

@module
abstract class RegisterModule {
  @preResolve
  Future<SharedPreferences> get prefs => SharedPreferences.getInstance();
}

I followed this question on StackOverflow but it did not work. My error is as follows:

The following assertion was thrown building SignInForm(dependencies: [MediaQuery]):
Object/factory with  type SignInFormBloc 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'

The auto-generated-injection code looks like follows:

Future<GetIt> $initGetIt(
  GetIt get, {
  String environment,
  EnvironmentFilter environmentFilter,
}) async {
  final gh = GetItHelper(get, environment, environmentFilter);
  final registerModule = _$RegisterModule();
  gh.factory<DatosBauServerApiHelper>(() => DatosBauServerApiHelper());
  gh.factory<DatosBauServerAuth>(
      () => DatosBauServerAuth(get<DatosBauServerApiHelper>()));
  gh.lazySingleton<IAuthFacade>(
      () => DatosBauServerAuthFacade(get<DatosBauServerAuth>()));
  final sharedPreferences = await registerModule.prefs;
  gh.factory<SharedPreferences>(() => sharedPreferences);
  gh.factory<SignInFormBloc>(() => SignInFormBloc(get<IAuthFacade>()));
  return get;
}

class _$RegisterModule extends RegisterModule {}

Solution

  • Package Get it

    LocalSharedPreferences class

    abstract class LocalSharedPreferences {
       // ...
    }
    

    LocalSharedPreferencesImpl class

    class LocalSharedPreferencesImpl extends LocalSharedPreferences {
       // ...
       // Use your globalSharedPrefs variable here
    }
    

    Another dart file

    GetIt locator = GetIt.instance;
    
    setupServicesLocator() {
      locator.registerLazySingleton<LocalSharedPreferences>(() => LocalSharedPreferencesImpl());
    }
    

    Your main.dart file

    SharedPreferences globalSharedPrefs;
    
    void main() async {
      /* ENSURE ASYNC WILL NOT GENERATE RUNTIME ERROR */
      WidgetsFlutterBinding.ensureInitialized();
    
      /* GLOBAL SERVICES */
      setupServicesLocator();
    
      /* Initialize your globalSharedPreferences variable here */
      globalSharedPrefs = await SharedPreferences.getInstance();
    }