pass value from api call from splash screen

Viewed 60

I have a splash screen, where I call an api, and get a string response. I save the response as alertMessage. I want to pass this string (alertMessage) to the next screen.

I make the api call in initState, like this:

  @override
  void initState() {
    PreLoadApi().fetchPreLoad().then((value){

    int numberOfEntries = GlobalCall.outcomes.categoryData[0].categoryTextAndID.length;

      for (int i = 0; i < numberOfEntries; i++) {
      String entry = GlobalCall.outcomes.categoryData[0].categoryTextAndID[i].categoryTextDetail;;
      print('2124: From preload, value $i: $entry');
          if(i==0){

// Here I set alertMessage
        alertMessage = entry;

              }
      print('2124: AlertMessage from initState: $alertMessage');
    }

  });

Now, my build method is like this:

 @override
  Widget build(BuildContext context) {

    print('2124: AlertMessage from build: $alertMessage');

    ScreenUtil.init(context, designSize: Size(750, 1334), allowFontScaling: false);

    return new SplashScreen(
      seconds: 3,
      navigateAfterSeconds: token != '' ? new MenuScreen(alertMessage: alertMessage): new LoginScreen(alertMessage: alertMessage),
      //title: new Text('Welcome In SplashScreen'),
      image: new Image.asset('assets/logo/ic_logo.png'),
      backgroundColor: Colors.white,
      styleTextUnderTheLoader: new TextStyle(),
      photoSize: MediaQuery.of(context).size.width * 0.5,
      loaderColor: Colors.blue,
    );
  }
}

Now, I understand the problem, but don't know the solution. The build method is called before the api result comes in. So when I call return new SplashScreen, the value of alertMessage is still null. Even though the splash screen stands for 3 seconds, but when its first called he alertMessage value is null. How can I make it that the value alertMessage will be updated once the api result comes in?

I hope its clear.

Thanks

1 Answers

Seems you may want to look at how you can transform your API call into a FutureBuilder. You have an unused value coming back from your API. Presumably you might want to use that value in obtaining the precise entry you need to build the widget properly.

If you are just waiting for a single value, then a FutureBuilder applies or if a number of values come back that would imply using a StreamBuilder.

It's a bit unclear what the API fetch is pointing to but here is an example from the Flutter docs on how to implement a FutureBuilder. There are many other examples online that demonstrate how to use your fetch routine inside a function whose return signature matches a FutureBuilder.

Tips

  • You probably want to move your API call into a FutureBuilder that wraps around your widget
  • If you need to save state value it will likely be a local variable in the _State class

Check the video in the source.

Source

import 'package:flutter/material.dart';


void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: _title,
      home: MyStatefulWidget(),
    );
  }
}

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

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  final Future<String> _calculation = Future<String>.delayed(
    const Duration(seconds: 2),
    () => 'Data Loaded',
  );

  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.headline2!,
      textAlign: TextAlign.center,
      child: FutureBuilder<String>(
        future: _calculation, // a previously-obtained Future<String> or null
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
          List<Widget> children;
          if (snapshot.hasData) {
            children = <Widget>[
              const Icon(
                Icons.check_circle_outline,
                color: Colors.green,
                size: 60,
              ),
              Padding(
                padding: const EdgeInsets.only(top: 16),
                child: Text('Result: ${snapshot.data}'),
              )
            ];
          } else if (snapshot.hasError) {
            children = <Widget>[
              const Icon(
                Icons.error_outline,
                color: Colors.red,
                size: 60,
              ),
              Padding(
                padding: const EdgeInsets.only(top: 16),
                child: Text('Error: ${snapshot.error}'),
              )
            ];
          } else {
            children = const <Widget>[
              SizedBox(
                width: 60,
                height: 60,
                child: CircularProgressIndicator(),
              ),
              Padding(
                padding: EdgeInsets.only(top: 16),
                child: Text('Awaiting result...'),
              )
            ];
          }
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: children,
            ),
          );
        },
      ),
    );
  }
}
Related