Call async functions in build method flutter

2,517

Solution 1

You are using an asynchronous value in a rendering process (the build function of a stateful/stateless widget) which is synchronous. You can't just put a Future of String into a place of a String. It won't work. Why? Because it is of a different type, and you need special methods to convert a variable from one type to another.

In this case, you might want to transform this Future into a String asynchronously during the build process. You can use a FutureBuilder for that.

return FutureBuilder<String>(
  future: _myRead,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return Text(snapshot.data);
    } else {
      return Text('awaiting the future');
    }
  },
);

If you don't transform this Future into a String to be rendered, it will just be an Instance of Future.

Solution 2

you should use a FutureBuilder if you wanna render something that takes time (asynchronous)

FutureBuilder(
 future:_myRead,
 builder: (ctx,snapshot) {
  if(snapshot.connectionState == connectionState.waiting) {
   return // your waiting Widget Ex: CircularLoadingIndicator();
} else if (snapshot.hasData) { 
  return Text(snapshot.data.toString()); // toString() is just to be safe
} else { //probably an error occured
  return Text('Something went wrong ...');
}
Share:
2,517
Micheal Ross
Author by

Micheal Ross

Updated on December 21, 2022

Comments

  • Micheal Ross
    Micheal Ross over 1 year

    I need to get the text wrote inside a ".txt" file, save it in a variable and give it to a Text, inside a TextField. The idea is to write the user input in a ".txt" file so he can read what he wrote when needed on the TextField.

    All works, when I read the file it takes the right content but when I store it in a variable to use it Text(var_name...) well what I read on the screen is "Instance of 'Future'".

    I know this problem comes from a bad handling of async and future but I would like to really understand why this isn't working.

    This is my code :

    Future<String> get _localPath async {
     final directory = await getApplicationDocumentsDirectory();
     return directory.path;
    }
    
    Future<File> get _localBio async {
     final path = await _localPath;
     print(path);
     return File('$path/bio.txt');
    }
    
    Future<File> _write(String text, String filename) async {
    final file = await _localBio;
    
    // Write the file.
    return file.writeAsString(text);
    }
    
    Future<String> _read() async {
      try {
        final file = await _localBio;
         String body = await file.readAsString();
      // Read the file.
        return body;
      } catch (e) {
      // If encountering an error, return 0.
        return "Can't read";
      }
    }
    
    Future<String>_MyRead() async {
     String read_ = await _read();
     print(read_);
     return read_;
    }
    

    Please write a full answer, I tried a lots of video, forums...Don't just tell me to do var str= _MyRead().then((value) => value); Maybe it can be the answer but please write 2 more lines because I want to understand why this isn't working. I took the code from dev official documentation.

    • Benedikt J Schlegel
      Benedikt J Schlegel almost 4 years
      Have you confirmed it writes the string correctly? The issue is just in reading?
    • Micheal Ross
      Micheal Ross almost 4 years
      Currently I wrote the string in the file by my hand and the "write" doesn't work, I tested it now. I'm new in Flutter maybe I'm calling the functions in a bad way... In the variable, after reading, "null" is stored.
  • Micheal Ross
    Micheal Ross almost 4 years
    Oooooh ok now I understand. Thank you very clear. I will study this FutureBuilder. I thought that using a ".then" I could transform a "Future<String>" to String. The only way to do this transformation is with a "FutureBuilder"?