0

Variable dependent widgets are processed before FutureBuilder finishes execution.
With the following code 'subtraction was called on null' error appears.
- Is it possible to get word (problem) variable before creating rest widgets in layout with it?

List<int> word = [];
int length;
var rng = new Random();
  body: Column(children: [
    Container(
          child: FutureBuilder<Quote>(
            future: getQuote(), 
            builder: (BuildContext context, AsyncSnapshot<Quote> snapshot) {
              if (snapshot.hasData) {  
                word = snapshot.data.tag.runes.toList();
                word.shuffle();
                length = word.length;
                return Center(
                  child: Column(
                    children: <Widget>[
                      Text(snapshot.data.tag), 
                      Image.network(
                          '${snapshot.data.url}',
                      ), //displays the quote's author
                    ],
                  ),
                );
              } else { 
              return CircularProgressIndicator();
            },
          ),

    ),
        Container(
     height:75,
      child: GridView.count(
        crossAxisCount: 5,
        children: List.generate(5, (int index) {
          return Center(
            child:  FlatButton(
              child: Text(
                  String.fromCharCode(

Next line throws error with null

               index = (length-word.length)<3 ? word.removeAt(rng.nextInt(word.length))
                              : 65+rng.nextInt(25)
                  ),
...

Function, which loads data from url

Future<Quote> getQuote() async {
var API_KEY = '12892554-73418a404928f2a4e42121633';
final object = generateNoun().take(1);
String url = "https://pixabay.com/api/? 
key="+API_KEY+"&q="+Uri.encodeFull(object.toString());
final response = await http.get(url);
if (response.statusCode == 200) {
return Quote.fromJson(json.decode(response.body));
}
}
mktplus
  • 504
  • 1
  • 4
  • 17

1 Answers1

0

Resolved by packing the whole layout tree in the FutureBuilder and placing whole thing in body within Scaffold.

@override
Widget build(BuildContext context) {
var my_layout = FutureBuilder<Quote>(
    future: getQuote(), //sets the getQuote method as the expected Future
    builder: (BuildContext context, AsyncSnapshot<Quote> snapshot) {
      switch (snapshot.connectionState) {
        case ConnectionState.none:
          return new Text('No preferences');
        case ConnectionState.waiting:
          return CircularProgressIndicator();
        default:
          if (snapshot.hasError) {
            return InkWell(
                child: Padding(
                  padding: const EdgeInsets.all(32.0),
                  child: Text("ERROR OCCURRED, Tap to retry !"),
                ),
                onTap: () => setState(() {}));
          }
          else { // this runs when data is retrieved properly

// set values for all variables, which depend on FutureBuilder and required in rest widgets

// put ALL widgets, that were previously in body //

return Scaffold(
  appBar: AppBar(
    title: Text('Guess word'),
  ),
  body: my_layout,
);
// close build method
mktplus
  • 504
  • 1
  • 4
  • 17