4

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.

2
  • Have you confirmed it writes the string correctly? The issue is just in reading? Commented May 29, 2020 at 16:14
  • 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. Commented May 29, 2020 at 16:21

2 Answers 2

8

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.

Sign up to request clarification or add additional context in comments.

1 Comment

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"?
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 ...');
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.