When I change the state upon which a specific futurebuilder widget relies, the widget is not redrawn until the async task completes. I want the widget to be redrawn immediately once the state changes. Below is the code for the futurebuilder:
child: new FutureBuilder(
future: _api.getListOfTourneys(searchTerm, filterChecks, pageNum),
builder: (context, snapshot) {
if (snapshot.hasData) {
if(!(snapshot.data is List)){
return new TourneyItem(snapshot.data['tournament']);
}
return new Expanded(
child: ListView.builder(
shrinkWrap: false,
scrollDirection: Axis.vertical,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return TourneyItem(snapshot.data[index]);
},
));
} else if (snapshot.hasError) {
return new Text("No results found");
} else {
return new CircularProgressIndicator();
}
},
)
I think FutureBuilder only builds once at start then everytime async task is compelted. So when we navigate to screen FutureBuilder is build at start then when async task is complete, then for other calls (except first) FutureBuilder only builds after async task is completed.
I also needed rebuild FutureBuilder at start of async call, I solved this issue by using snapshot.connectionState
Insider builder of FutureBuilder
if(snapshot.connectionState == ConnectionState.done){
if(snapshot.hasData){
//Show data here
}else{
//Show error here
}
}else{
//Show progress
}
You can't do that using FutureBuilder. If you want to build more than "initial" + "done" don't use FutureBuilder.
Instead you can use a Stream
and StreamBuilder
by submitting your future result to the stream.
class Foo extends StatefulWidget {
@override
_FooState createState() => _FooState();
}
class _FooState extends State<Foo> {
StreamController streamController;
@override
void initState() {
load();
super.initState();
}
load() async {
streamController.add("Loading");
await Future.delayed(Duration(seconds: 1));
streamController.add("Done");
}
@override
void didUpdateWidget(Foo oldWidget) {
if (somethingChanged) {
load();
}
super.didUpdateWidget(oldWidget);
}
@override
void dispose() {
streamController.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return StreamBuilder<String>(
stream: streamController.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return new Text(snapshot.data);
} else if (snapshot.hasError) {
return new Text("Error");
} else {
return new Text("Nothing");
}
},
);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With