'Flutter call Firebase Function before loading Widget

I am still relatively new to Flutter and I am trying to figure out how to construct a Widget UI using external data... I have written a Firebase Function that when called generates a GetStream.io user token so that I can send that token to the Feed page of my app. I have posted my code below, it doesn't work but if someone could help it would be much appreciated.

What I am attempting to do is when this Widget initiates, set isLoading to true, call the function 'getStreamUserToken' which returns a token, once retrieved, set 'isLoading' to false and pass the token to the FeedScreen widget in the main body so that it can handle the Stream Feed.

import 'package:clubs/components/loading.dart';
import 'package:clubs/home/feed_screen.dart';
import 'package:cloud_functions/cloud_functions.dart';
import 'package:flutter/material.dart';

class ClubsApp extends StatefulWidget {
  const ClubsApp({Key? key}) : super(key: key);

  @override
  State<ClubsApp> createState() => _ClubsAppState();
}

class _ClubsAppState extends State<ClubsApp> {
  bool isLoading = false;
  String? token;

  void setIsLoading() {
    setState(() {
      isLoading = !isLoading;
    });
  }

  @override
  void initState() {
    super.initState();
    asyncMethod();
    print('Token: ' + token!);
    setIsLoading();
  }

  void asyncMethod() async {
    token = await _getStreamToken();
  }

  @override
  Widget build(BuildContext context) {
    return isLoading
        ? const Loading()
        : Scaffold(
            body: FeedScreen(token: token!), // TODO: implement page switching
            bottomNavigationBar: BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              items: const [
                BottomNavigationBarItem(icon: Icon(Icons.home), label: "Home"),
                BottomNavigationBarItem(
                    icon: Icon(Icons.groups_outlined), label: "Members"),
                BottomNavigationBarItem(
                    icon: Icon(Icons.water_outlined), label: "Pontoon"),
              ],
              selectedItemColor: const Color(0xff202441),
              unselectedItemColor: const Color(0xFF02BFAB),
              showUnselectedLabels: true,
            ),
          );
  }

  Future<String?> _getStreamToken() async {
    HttpsCallable callable =
        FirebaseFunctions.instance.httpsCallable('getStreamUserToken');
    final results = await callable();
    String token = results.data;
    return token;
  }
}


Solution 1:[1]

You need to wait for asyncMethod to complete, before calling setIsLoading.

The simplest way to do that, is to hook it's then callback:

@override
void initState() {
  super.initState();
  asyncMethod().then((token) {
    print('Token: ' + token!);
    setIsLoading();
  })
}

If you want to return the value, you can:

@override
void initState() {
  super.initState();
  return asyncMethod().then((token) {
    setIsLoading();
    return token;
  })
}

I recommend reading up on Dart Futures and taking the Asynchronous programming: futures, async, await codelab

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1