injectable
injectable copied to clipboard
Async singleton not working properly
I have this singleton:
final class OpenWeather {
final String baseURL, apiKey, baseWeatherIconUrl;
const OpenWeather._({required this.baseURL, required this.apiKey, required this.baseWeatherIconUrl});
static OpenWeather? _instance;
static Future<void> init() async {
if (_instance != null) return;
try {
await dotenv.load(fileName: 'my.env');
_instance = OpenWeather._(
baseURL: dotenv.get('BASE_API_URL'),
apiKey: dotenv.get('API_KEY'),
baseWeatherIconUrl: dotenv.get('BASE_WEATHER_ICON_URL'),
);
} catch (e) {
_instance = null;
throw Exception('Env file cannot be loaded or some required field was not found.');
}
}
static OpenWeather get instance {
if (_instance != null) return _instance!;
throw Exception('OpenWeather was not initialized.');
}
}
I'm new with this package (and get_it too) so I'm getting a hard time about how to transform this class to use it with Injection package.
Another question is about how to notify other singletons to await to be created until an instance of OpenWeather exists (after init
async method to be executed), example:
@singleton
class MyClass {
void myMethod() {
final value = OpenWeather.instance.baseURL;
...
<code using this value>
...
}
}
Try N° 1:
@singleton
final class OpenWeather {
final String baseURL, apiKey, baseWeatherIconUrl;
const OpenWeather({required this.baseURL, required this.apiKey, required this.baseWeatherIconUrl});
@factoryMethod
static Future<OpenWeather> init() async {
try {
await dotenv.load(fileName: 'my.env');
return OpenWeather(
baseURL: dotenv.get('BASE_API_URL'),
apiKey: dotenv.get('API_KEY'),
baseWeatherIconUrl: dotenv.get('BASE_WEATHER_ICON_URL'),
);
} catch (e) {
throw Exception('Env file cannot be loaded or some required field was not found.');
}
}
}
@singleton
class MyClass {
final OpenWeather openWeather;
void myMethod(this.openWeather) {
final value = openWeather.baseURL;
...
<code using this value>
...
}
}
import 'di.config.dart';
final getIt = GetIt.instance;
@InjectableInit(
preferRelativeImports: true,
)
void configureDependencies() => getIt.init();
void main() async {
configureDependencies();
runApp(const AppProviders(child: MyApp()));
}
When running dart run build_runner build --delete-conflicting-outputs
, it seems to be all OK so to check it I wanted to print a singleton value to my console from the home file of my app:
@RoutePage()
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
final baseUrl = getIt<OpenWeather>().baseURL;
print('baseUrl: $baseUrl');
return Scaffold(
...
But I get this error message:
Launching lib/main.dart on Pixel 3a in debug mode...
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Connecting to VM Service at ws://127.0.0.1:46799/xrh7AgjvmbE=/ws
════════ Exception caught by widgets library ═══════════════════════════════════
The following StateError was thrown building HomeScreen(dirty):
Bad state: You tried to access an instance of OpenWeather that is not ready yet
The relevant error-causing widget was:
HomeScreen HomeScreen:file:.../flutter_weather2/lib/config/routes/app_router.gr.dart:30:22
When the exception was thrown, this was the stack:
#0 throwIfNot (package:get_it/get_it_impl.dart:12:19)
#1 _GetItImplementation.get (package:get_it/get_it_impl.dart:434:7)
#2 _GetItImplementation.call (package:get_it/get_it_impl.dart:464:12)
#3 SearchScreen.build (package:flutter_weather2/modules/weather/3_presentation/2_screens/home/home_screen.dart:16:26)
#4 StatelessElement.build (package:flutter/src/widgets/framework.dart:5541:49)
#5 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5471:15)
#6 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#7 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5453:5)
#8 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5447:5)
... Normal element mounting (25 frames)
#33 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#34 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#35 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
... Normal element mounting (50 frames)
#85 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#86 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#87 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
... Normal element mounting (362 frames)
#449 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#450 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#451 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
... Normal element mounting (77 frames)
#528 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#529 Element.updateChild (package:flutter/src/widgets/framework.dart:3831:20)
#530 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#531 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#532 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#533 StatefulElement.update (package:flutter/src/widgets/framework.dart:5657:5)
#534 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#535 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#536 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#537 ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#538 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#539 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#540 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#541 ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#542 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#543 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#544 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#545 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#546 StatefulElement.update (package:flutter/src/widgets/framework.dart:5657:5)
#547 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#548 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#549 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#550 StatelessElement.update (package:flutter/src/widgets/framework.dart:5547:5)
#551 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#552 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#553 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#554 ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#555 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#556 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#557 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#558 ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#559 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#560 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#561 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#562 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#563 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2895:19)
#564 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:984:21)
#565 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:457:5)
#566 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1325:15)
#567 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1255:9)
#568 SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:978:7)
#572 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
(elided 3 frames from class _Timer and dart:async-patch)
════════════════════════════════════════════════════════════════════════════════
So Where/which is the problem?
Try N° 2:
@Singleton()
final class OpenWeather {
final String baseURL, apiKey, baseWeatherIconUrl;
OpenWeather({required this.baseURL, required this.apiKey, required this.baseWeatherIconUrl});
@FactoryMethod(preResolve: true)
static Future<OpenWeather> init() async {
try {
await dotenv.load(fileName: 'assets/env/openweather.env');
return OpenWeather(
baseURL: dotenv.get('BASE_API_URL'),
apiKey: dotenv.get('API_KEY'),
baseWeatherIconUrl: dotenv.get('BASE_WEATHER_ICON_URL'),
);
} catch (e) {
throw Exception('Env file cannot be loaded or some required field was not found.');
}
}
}
@InjectableInit(
preferRelativeImports: true,
)
Future<void> configureDependencies() async => GetIt.I.init();
void main() async {
await configureDependencies();
runApp(const AppProviders(child: MyApp()));
}
But I get this error message:
Launching .../flutter_weather2/lib/main.dart on Pixel 3a in debug mode...
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Connecting to VM Service at ws://127.0.0.1:41983/OxXw1kwrW-w=/ws
════════ Exception caught by widgets library ═══════════════════════════════════
The following StateError was thrown building SearchScreen(dirty):
Bad state: GetIt: Object/factory with type OpenWeather 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?)
The relevant error-causing widget was:
SearchScreen SearchScreen:file:.../flutter_weather2/lib/config/routes/app_router.gr.dart:30:22
When the exception was thrown, this was the stack:
#0 throwIfNot (package:get_it/get_it_impl.dart:12:19)
#1 _GetItImplementation._findFactoryByNameAndType (package:get_it/get_it_impl.dart:396:5)
#2 _GetItImplementation.get (package:get_it/get_it_impl.dart:424:29)
#3 _GetItImplementation.call (package:get_it/get_it_impl.dart:464:12)
#4 SearchScreen.build (package:flutter_weather2/modules/weather/3_presentation/2_screens/search/search_screen.dart:16:26)
#5 StatelessElement.build (package:flutter/src/widgets/framework.dart:5541:49)
#6 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5471:15)
#7 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#8 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:5453:5)
#9 ComponentElement.mount (package:flutter/src/widgets/framework.dart:5447:5)
... Normal element mounting (25 frames)
#34 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#35 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#36 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
... Normal element mounting (50 frames)
#86 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#87 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#88 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
... Normal element mounting (362 frames)
#450 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#451 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#452 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
... Normal element mounting (77 frames)
#529 Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#530 Element.updateChild (package:flutter/src/widgets/framework.dart:3831:20)
#531 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#532 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#533 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#534 StatefulElement.update (package:flutter/src/widgets/framework.dart:5657:5)
#535 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#536 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#537 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#538 ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#539 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#540 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#541 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#542 ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#543 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#544 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#545 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#546 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#547 StatefulElement.update (package:flutter/src/widgets/framework.dart:5657:5)
#548 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#549 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#550 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#551 StatelessElement.update (package:flutter/src/widgets/framework.dart:5547:5)
#552 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#553 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#554 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#555 ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#556 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#557 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#558 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#559 ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#560 Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#561 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#562 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#563 Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#564 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2895:19)
#565 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:984:21)
#566 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:457:5)
#567 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1325:15)
#568 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1255:9)
#569 SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:978:7)
#573 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
(elided 3 frames from class _Timer and dart:async-patch)
════════════════════════════════════════════════════════════════════════════════
Application finished.
Exited.
Try N° 3:
@Singleton(signalsReady: true)
final class OpenWeather {
final String baseURL, apiKey, baseWeatherIconUrl;
/* -------------------------------------------------------------------------------------- */
OpenWeather({required this.baseURL, required this.apiKey, required this.baseWeatherIconUrl}) {
getIt.signalReady(this);
}
/* -------------------------------------------------------------------------------------- */
@FactoryMethod()
static Future<OpenWeather> init() async {
try {
await dotenv.load(fileName: 'assets/env/openweather.env');
return OpenWeather(
baseURL: dotenv.get('BASE_API_URL'),
apiKey: dotenv.get('API_KEY'),
baseWeatherIconUrl: dotenv.get('BASE_WEATHER_ICON_URL'),
);
} catch (e) {
throw Exception('Env file cannot be loaded or some required field was not found.');
}
}
}
void main() async {
configureDependencies();
await getIt.allReady();
runApp(const AppProviders(child: MyApp()));
}
But I get this error message:
Launching .../flutter_weather2/lib/main.dart on 192.168.56.101:5555 in debug mode...
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Connecting to VM Service at ws://127.0.0.1:37787/zwYCVaXC1xA=/ws
E/flutter ( 2324): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Exception: Env file cannot be loaded or some required field was not found.
E/flutter ( 2324): #0 OpenWeather.init (file:///.../flutter_weather2/lib/config/servers/open_weather_server.dart:25:7)
E/flutter ( 2324): <asynchronous suspension>
E/flutter ( 2324): #1 _GetItImplementation._register.<anonymous closure>.<anonymous closure> (package:get_it/get_it_impl.dart:1093:44)
E/flutter ( 2324): <asynchronous suspension>
E/flutter ( 2324): #2 FutureGroup.add.<anonymous closure> (package:async/src/future_group.dart:79:15)
E/flutter ( 2324): <asynchronous suspension>
E/flutter ( 2324):
Removing try..catch
the error message is:
Launching .../flutter_weather2/lib/main.dart on 192.168.56.101:5555 in debug mode...
✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Connecting to VM Service at ws://127.0.0.1:34433/Fep90TXZAEw=/ws
E/flutter ( 2266): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Bad state: This instance of the type OpenWeather is not available in GetIt If you have registered it as LazySingleton, are you sure you have used it at least once?
E/flutter ( 2266): #0 throwIf (package:get_it/get_it_impl.dart:7:18)
E/flutter ( 2266): #1 _GetItImplementation._findFactoryByInstance (package:get_it/get_it_impl.dart:1245:5)
E/flutter ( 2266): #2 _GetItImplementation.signalReady (package:get_it/get_it_impl.dart:1280:28)
E/flutter ( 2266): #3 new OpenWeather (file:.../flutter_weather2/lib/config/servers/open_weather_server.dart:12:11)
E/flutter ( 2266): #4 OpenWeather.init (file:.../flutter_weather2/lib/config/servers/open_weather_server.dart:19:14)
E/flutter ( 2266): <asynchronous suspension>
E/flutter ( 2266): #5 _GetItImplementation._register.<anonymous closure>.<anonymous closure> (package:get_it/get_it_impl.dart:1093:44)
E/flutter ( 2266): <asynchronous suspension>
E/flutter ( 2266): #6 FutureGroup.add.<anonymous closure> (package:async/src/future_group.dart:79:15)
E/flutter ( 2266): <asynchronous suspension>
E/flutter ( 2266):
Observations:
- It seems these codes:
@Singleton(signalsReady: true)
final class OpenWeather {
...
@FactoryMethod()
static Future<OpenWeather> init() async {
...
And
@Singleton()
final class OpenWeather {
...
@FactoryMethod(preResolve: true)
static Future<OpenWeather> init() async {
...
do the same thing but I don't know because the README file offers very basic help which does not allow proper use of the package, so which would be the correct solution to this problem?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions