How to use Injectable for this singleton?

50 Views Asked by At

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 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>
    ...
  }
}

PS 1. my n-try:

@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?

0

There are 0 best solutions below