Description
I would like to have the lazy singleton instance to be retained as long as its used, but destroyed when it's no longer in use. I know it sounds like a factory, but hear me out.
The project I work on currently is implementing the Clean Architecture, where repositories are registered as factories and requested the use-case classes. We write something such as:
class Repo {
String getFoo() => "foo";
}
GetIt.instance.registerFactory(() => Repo());
class UseCase1 {
String call() => GetIt.instance.get<Repo>().getFoo();
}
class UseCase2 {
String call() => GetIt.instance.get<Repo>().getFoo();
}
class UseCase3 {
String call() => GetIt.instance.get<Repo>().getFoo();
}
GetIt.instance.registerFactory(() => UseCase1());
GetIt.instance.registerFactory(() => UseCase2());
GetIt.instance.registerFactory(() => UseCase3());
class MyBloc {
UseCase1 usecase1 = GetIt.instance()
UseCase2 usecase2 = GetIt.instance()
UseCase3 usecase3 = GetIt.instance()
}
When doing ↑, repositories get instantiated quite too often (everytime UsecaseX.call
get called) so it's not ideal.
class Repo {
String getFoo() => "foo";
}
GetIt.instance.registerFactory(() => Repo());
class UseCase1 {
Repo repo = GetIt.instance()
String call() => this.repo.getFoo();
}
class UseCase2 {
Repo repo = GetIt.instance()
String call() => this.repo.getFoo();
}
class UseCase3 {
Repo repo = GetIt.instance()
String call() => this.repo.getFoo();
}
GetIt.instance.registerFactory(() => UseCase1());
GetIt.instance.registerFactory(() => UseCase2());
GetIt.instance.registerFactory(() => UseCase3());
class MyBloc {
UseCase1 usecase1 = GetIt.instance()
UseCase2 usecase2 = GetIt.instance()
UseCase3 usecase3 = GetIt.instance()
}
We can try to make it better. When doing ↑, repositories get created less often but still there's one instance per Usecase instances, so still not ideal.
class Repo {
String getFoo() => "foo";
}
GetIt.instance.registerLazySingleton(() => Repo());
class UseCase1 {
String call() => GetIt.instance.get<Repo>().getFoo();
}
class UseCase2 {
String call() => GetIt.instance.get<Repo>().getFoo();
}
class UseCase3 {
String call() => GetIt.instance.get<Repo>().getFoo();
}
GetIt.instance.registerFactory(() => UseCase1());
GetIt.instance.registerFactory(() => UseCase2());
GetIt.instance.registerFactory(() => UseCase3());
class MyBloc {
UseCase1 usecase1 = GetIt.instance()
UseCase2 usecase2 = GetIt.instance()
UseCase3 usecase3 = GetIt.instance()
}
When doing ↑, repo instance remains in memory forever, so it's currently the best but it clutters the memory forever, so it's even better... but still not there 100%.
What I would like to have is a Cached Instance which could be very similar to registerLazySingleton
but the reference to the instance would be retained in a WeakReference in GetIt, so that it is a singleton as long as it is used somewhere, but as soon as every user-land reference is gone, it would turn to null
and be garbage collected.
We currently are experimenting wrapping our UseCase
class with a Finalizer, so that we can call manually resetLazySingleton()
which would have the same effect. What i'm proposing/requesting is that it became a feature of the library 🙏
Thank you for your time reading this