Search code examples
flutterdependency-injectionsharedpreferencesflutter-dependenciesinjectable

How Use shared preference with injectable and get_it in flutter?


im using injectable and get_it package in flutter i have a shared preference class :

@LazySingleton()
class SharedPref {
  final String _token = 'token';
  SharedPreferences _pref;

  SharedPref(this._pref);

  Future<String> getToken() async {
    return _pref.getString(_token) ?? '';
  }

  Future<void> setToken(String token) async {
    await _pref.setString(_token, token);
  }
}

this class inject as LazySingleton and i have a module for inject the shared preference :

@module
abstract class InjectableModule {

 @lazySingleton
 Future<SharedPreferences> get prefs => SharedPreferences.getInstance();
}

in bloc class im using SharedPref class :

@injectable
class LoginCheckBloc extends Bloc<LoginCheckEvent, LoginCheckState> {
  final SharedPref sharedPref;

  LoginCheckBloc({@required this.sharedPref}) : super(const LoginCheckState.initial());

  @override
  Stream<LoginCheckState> mapEventToState(
    LoginCheckEvent event,
  ) async* {
    if (event is CheckLogin) {
      final String token = await sharedPref.getToken();
      if (token.isEmpty){
        yield const LoginCheckState.notLogin();
      }else{
        yield const LoginCheckState.successLogin();
      }
    }
  }
}

when i use LoginCheckBloc with getIt<> i have an error for injecting the shared prefrence :

BlocProvider<LoginCheckBloc>(
          create: (BuildContext context) => getIt<LoginCheckBloc>()..add(CheckLogin()),
        ),

the error message is :

You tried to access an instance of SharedPreferences that was not ready yet
'package:get_it/get_it_impl.dart':
Failed assertion: line 272 pos 14: 'instanceFactory.isReady'

how use shared preference with injectable ??


Solution

  • It worked on mine when I used @preResolve the SharedPreference

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

    and then on the injectable class you write this

    final GetIt getIt = GetIt.instance;
    
    @injectableInit
    Future<void> configureInjection(String env) async {
     await $initGetIt(getIt, environment: env);
    }
    

    and on the main class

    void main() async {
     WidgetsFlutterBinding.ensureInitialized();
     await configureInjection(Environment.prod);
     runApp(MyApp());
    }