skip to Main Content

I am a noob with Flutter/Dart/Firebase so I might be doing something obviously wrong:

class RemoteConfigService {
  static final RemoteConfigService _singleton = RemoteConfigService._internal();

  factory RemoteConfigService() {
    return _singleton;
  }

  RemoteConfigService._internal();

  final FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.instance;

  Future<void> initialize() async {
    await remoteConfig.fetchAndActivate();
  }

  String get apiKey => remoteConfig.getString('apiKey');
}

Now I am trying to access apiKey in my main and it works as i see its value printed

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await RemoteConfigService().initialize();
  String key = RemoteConfigService().apiKey;
  print(key);
}

But when I try the same in view it doesn’t work?

class _TestViewState extends State<TestView> {
....

Future<String> makeApiCall() async {
    String apiKey = RemoteConfigService().apiKey;  //coming back as empty
}
}

If it’s already working in main() during init why not here. It’s a singleton class. Any workarounds?

Tried a bunch of things including initializing RemoteConfigService() inside the makeApiCall() method and still shows up as empty.

2

Answers


  1. Chosen as BEST ANSWER

    Not sure what is up but I manually uninstalled the app on my phone before running "flutter run" and it worked this time.


  2. The issue you are facing might be related to the timing of the initialization of the RemoteConfigService. When you call RemoteConfigService().initialize() in your main() method, it initiates the fetching and activation of remote configurations, but this process takes some time to complete. If you are trying to access the apiKey immediately after calling makeApiCall(), the configurations might not have been fetched and activated yet, resulting in an empty value.

    To handle asynchronous operations like this, you can utilize FutureBuilder in your widget tree. FutureBuilder allows you to perform asynchronous operations and rebuild the widget tree when the operation is complete.

    Here’s how you can modify your TestView class using FutureBuilder:

    class TestView extends StatefulWidget {
      @override
      _TestViewState createState() => _TestViewState();
    }
    
    class _TestViewState extends State<TestView> {
      Future<String> _apiKeyFuture;
    
      @override
      void initState() {
        super.initState();
        _apiKeyFuture = RemoteConfigService().initialize().then((_) {
          return RemoteConfigService().apiKey;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
          future: _apiKeyFuture,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator(); // Show a loading indicator while fetching apiKey.
            } else if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            } else {
              String apiKey = snapshot.data;
              return Text('API Key: $apiKey');
            }
          },
        );
      }
    }
    
    

    In this modified code, the initialize() method of RemoteConfigService is called in the initState() method, and the FutureBuilder widget handles the asynchronous fetching of the API key. While the API key is being fetched and activated, a loading indicator is displayed. When the operation is complete, it displays the API key.

    Make sure to handle error cases appropriately in the FutureBuilder as well, depending on your use case.

    By using FutureBuilder, you ensure that the widget waits for the asynchronous operation to complete before trying to access the API key, preventing issues related to timing and asynchrony.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search