Skip to content

[Question] How to use registerLazySingletonAsync with SharedPreferences #273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ykaito21 opened this issue Apr 17, 2022 · 3 comments
Closed

Comments

@ykaito21
Copy link

ykaito21 commented Apr 17, 2022

I'm doing ResoCoder's TDD Clean Architecture Course, and it use get_it as DI.
It was created in 2019, I tried to create the updated version, but I couldn't find the clear way to handle the case. Am I doing something wrong? Should I use registerSingletonWithDependencies or Is there any better way?

This is the original code: get_it: ^3.1.0

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await init();
  runApp(MyApp());
}


final sl = GetIt.instance;

Future<void> init() async {
  //! Features - Number Trivia
  // Bloc
  sl.registerFactory(
    () => NumberTriviaBloc(
      concrete: sl(),
      inputConverter: sl(),
      random: sl(),
    ),
  );

  // Use cases
  sl.registerLazySingleton(() => GetConcreteNumberTrivia(sl()));
  sl.registerLazySingleton(() => GetRandomNumberTrivia(sl()));

  // Repository
  sl.registerLazySingleton<NumberTriviaRepository>(
    () => NumberTriviaRepositoryImpl(
      localDataSource: sl(),
      networkInfo: sl(),
      remoteDataSource: sl(),
    ),
  );

  // Data sources
  sl.registerLazySingleton<NumberTriviaRemoteDataSource>(
    () => NumberTriviaRemoteDataSourceImpl(client: sl()),
  );

  sl.registerLazySingleton<NumberTriviaLocalDataSource>(
    () => NumberTriviaLocalDataSourceImpl(sharedPreferences: sl()),
  );

  //! Core
  sl.registerLazySingleton(() => InputConverter());
  sl.registerLazySingleton<NetworkInfo>(() => NetworkInfoImpl(sl()));

  //! External
  final sharedPreferences = await SharedPreferences.getInstance();
  sl.registerLazySingleton(() => sharedPreferences);
  sl.registerLazySingleton(() => http.Client());
  sl.registerLazySingleton(() => DataConnectionChecker());
}

This is my updated version: get_it: ^7.2.0

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  init();
  await sl.isReady<SharedPreferences>();
  runApp(const MyApp());
}


final sl = GetIt.instance;

void init() {
  //! Features - Number Trivia
  // Bloc
  sl.registerFactory(() => NumberTriviaBloc(
        getConcreteNumberTrivia: sl(),
        getRandomNumberTrivia: sl(),
        inputConverter: sl(),
      ));

  // Use cases
  sl.registerLazySingleton(() => GetConcreteNumberTrivia(sl()));
  sl.registerLazySingleton(() => GetRandomNumberTrivia(sl()));

  // Repository
  sl.registerLazySingleton<NumberTriviaRepository>(
      () => NumberTriviaRepositoryImpl(
            localDataSource: sl(),
            remoteDataSource: sl(),
            networkInfo: sl(),
          ));

  // Data sources
  sl.registerLazySingleton<NumberTriviaRemoteDataSource>(
      () => NumberTriviaRemoteDataSourceImpl(
            client: sl(),
          ));
  sl.registerLazySingleton<NumberTriviaLocalDataSource>(
      () => NumberTriviaLocalDataSourceImpl(
            sharedPreferences: sl(),
          ));

  //! Core
  sl.registerLazySingleton(() => InputConverter());
  sl.registerLazySingleton<NetworkInfo>(() => NetworkInfoImpl(sl()));

  //! External
  // maybe I don't need lazy just registerSingletonAsync
  sl.registerLazySingletonAsync(() async => SharedPreferences.getInstance());
  sl.registerLazySingleton(() => http.Client());
  sl.registerLazySingleton(() => InternetConnectionChecker());
}
@escamoteur
Copy link
Collaborator

When a non async Singleton depends on one with an async initialization registerSingletonWithDependencies is your way to go.

@konstantins-v
Copy link

@ykaito21 , you can create an AbstractCache and SharedPreferenceImpl

import 'package:shared_preferences/shared_preferences.dart';

abstract class AbstractCache {
  getStringList(String key);
  Future<bool> setStringList(String key, List<String> value);
}

class SharedPreferenceCache extends AbstractCache {

  SharedPreferences cache;
  
  SharedPreferenceCache({
    required this.cache
  });

  @override
  getStringList(String key) async {
    var inst =  await SharedPreferences.getInstance();

    return inst.getStringList(key);
  }

  @override
  Future<bool> setStringList(String key, List<String> value) async {
    var inst =  await SharedPreferences.getInstance();

    return inst.setStringList(key, value);
  }
}

After that use AbstractClass in NumberTriviaLocalDataSourceImpl.

So and fix your di/service_locator.dart like:

  final sharedPreferences = await SharedPreferences.getInstance();
  s1.registerLazySingleton<AbstractCache>(() => SharedPreferenceCache(cache: sharedPreferences));

@swarajkumarsingh
Copy link

Step 1: Register your dependency(shared preferences)

class DependencyInjection {
static void setup(){ 
 GetIt.instance.registerLazySingletonAsync<SharedPreferences>(
  () => SharedPreferences.getInstance(),
);
await GetIt.instance.isReady<SharedPreferences>(); // Add this line
GetIt.instance.registerLazySingleton<SharedDataService>(
  () => SharedDataServiceImp(
    GetIt.instance<SecureStorageService>(),
    GetIt.instance<SharedPreferences>(),
  ),
 );
}

Step 2: Attach the function to main func
DependencyInjection.setup();

Step 3: Usage
final sf = getIt();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants