Update: Solved, look at the answer below.
I have a simple Text(initial text value is 'Empty') widget and a button at the top of the screen. When I click the button, I am loading a file that takes a long time to complete. While it is working to complete that, I want to change the Text widget to say 'Loading' and then display the content of the file once that task is finished loading the file.
I run the loading task in a Future and in my build function of the State class I am using a FutureBuilder widget to know what the Text widget should show based on if the task is complete yet or not.
The problem, I think, is that because dart is a single-threaded app, changing the text of the Text widget to 'Loading' doesn't get executed only after the task is completed, which beats the purpose (even when calling setState, because it is added to the event loop I believe where the Future is also scheduled to run).
Should I be running the long task in a separate Isolate? Is that the right way to go? I've been on this for a long time, hopefully someone can help, it's something that should be so simple..
This is the code I am using:
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String content = 'Empty';
Future<FileObject> file;
loadData() async {
// do the loading of the file here (that takes a LONG time)
file = /*loadfunction for the file (returns a Future, because it takes long)*/;
}
loadTask() {
setState(() {
content = 'Loading...';
});
loadData();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.black,
body: Column(
children: <Widget>[
buildTitle(),
buildContent(),
],
),
);
}
FutureBuilder<FileObject> buildContent() {
return FutureBuilder<FileObject>(
future: file,
builder: (BuildContext context, AsyncSnapshot<FileObject> snapshot) {
if (snapshot.hasData) {
content = snapshot.data.text; // The FileObject has a text property
}
return Expanded(
child: SingleChildScrollView(
child: Text(
content,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.lightBlue[100],
fontSize: 25.0,
fontWeight: FontWeight.normal,
),
),
),
);
},
);
}
Padding buildTitle() {
return Padding(
padding: const EdgeInsets.only(left: 8.0, top: 50.0, bottom: 30.0),
child: Row(
children: <Widget>[
IconButton(
icon: Icon(
Icons.update,
color: Colors.lightBlue[50],
),
onPressed: loadTask,
),
],
),
);
}
}