1

How can I make sure I have a state variable available after an async function call? My belief is because getValues() is async, it should "wait" until moving on to the next line. Thus, getValues() shouldn't exit and configValue() shouldn't be invoked until after my call to setState has finished. However the behavior I'm seeing it that values is an empty array in my Widget.

  late List values = [];

  @override
  void initState() {
    super.initState();
    getValues();
    configValue();
  }

  getValues() async {
    final String response = await rootBundle.loadString('assets/values.json');
    final vals = await json.decode(response)['values'];
    setState(() {
      values = vals;
    });
  }

  void configValue() {
    // How to make sure I have values[0] here?
  }

Thanks in advance!

PrimeTimeTran
  • 1,807
  • 2
  • 17
  • 29
  • 1
    `it should "wait"`. No, it shouldn't. That's actually what async is all about. It does it asynchronously. And that's why there is the `await` keyword. It makes you able to wait for them. – Ivo Jan 31 '23 at 10:34
  • Asynchronous functions return `Future`s, and `Future`s must be `await`ed (or have completion callbacks registered) to execute code when those `Future`s complete. Additionally, you should avoid asynchronous initialization in `initState` and use `FutureBuilder`. – jamesdlin Jan 31 '23 at 15:41

3 Answers3

2

You can change your getValues to this:

Future<List> getValues() async {
  final String response = await rootBundle.loadString('assets/values.json');
  final vals = await json.decode(response)['values'];
  return vals;
}

then create another middle function like this:

callasyncs() async {
   var result = await getValues();
   configValue(result);
}

and call it inside initState like this:

@override
void initState() {
  super.initState();
  callasyncs();
}

also change your configValue to this:

void configValue(List values) {
  // now you have updated values here.
}

here your both configValue and getValues are separated from each other and also your configValue will wait for the getValues result.

eamirho3ein
  • 16,619
  • 2
  • 12
  • 23
0

you need to use await before the method to complete the future. also can be use .then.

Future<void> getVids() async { //I prefer retuning value
  final String response = await rootBundle.loadString('assets/values.json');
  final vals = await json.decode(response)['values'];
  setState(() {
    values = vals;
  });
}

void configValue() async {
  await getVids();
   
}
Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56
0

Try the following code:

List? values;

@override
void initState() {
  super.initState();
  getValues();
  configValue();
}

Future<void> getVids() async {
  final String response = await rootBundle.loadString('assets/values.json');
  final vals = await json.decode(response)['values'];
  setState(() {
    values = vals;
  });
}

void configValue() {
  if (values != null) {
    if (values!.isNotEmpty) {
      …
    }
  }
}
My Car
  • 4,198
  • 5
  • 17
  • 50