Error Using FutureBuilder With Local JSON as Future

Issue

I am trying to load some json data and have used a futurebuilder to wait for the data to be available first then display it. When I try to load the data in DetailsView, I get two log messages Saying there’s no data and null, the screen errors out and after that returns back to normal and the json is logged to the console.

The exception thrown is The following NoSuchMethodError was thrown building FutureBuilder<String>(dirty, state: _FutureBuilderState<String>#cc31b): The method '[]' was called on null. Receiver: null.

Sample code:

body: Container(
      margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 15.0),
      child: FutureBuilder(
        future: DefaultAssetBundle.of(context).loadString("assets/my_data.json"), // validly referenced in pubspec and in right folder
        builder: (context, snapshot){
          if(!snapshot.hasData){
            print('no data'); // I understand it will be empty for now
          } else {
            print('hd');
          }
          var data = snapshot.data.toString();
          print(data); // null logged to console, is the future still empty at this point?
          final parsedData = json.decode(data);
          print('pd ${parsedData[1]}'); // this line is where it shows the method [] was called on null
          return data == null || data.isEmpty
              ? LoadingStrengths()
              : MyDataText();
              // : DailyStrengthText(day: widget.day, data: parsedData);
        },
      ),
    ),

The issues seem to be that:

  1. I am not handling the future properly
  2. I am not parsing the json properly, have attached a copy of it below.

Sample data:

[{
    "1": "Each day is an opportunity to start over again"
},
{
    "2": "Every man must at one point be tempted to hoist the black"
},
{
    "3": "Be kind to everyone you meet"
}]

I am trying to parse it by using the stringified numbers as key, to access the values. How do I make the model class for this or/and parse this json in the futurebuilder? Thanks.

——————————- EDIT —————————————-
Here’s the edited builder method, from which I was able to parse and print out the data:

if(!snapshot.hasData){
            print('no data yet');
            return LoadingStrengths();
          } else {
            print('hd');
            var data = snapshot.data.toString();
            parsedData = json.decode(data);
            print('pd ${parsedData[widget.day - 1]}');
          }
          return Text('${data[widget.day - 1]}'); // it errors out here

When I assign the value to the Text widget it errors out with this error message:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building FutureBuilder<String>(dirty, state: _FutureBuilderState<String>#cc19b):
The method '[]' was called on null.
Receiver: null
Tried calling: [](4)

The relevant error-causing widget was: 
FutureBuilder<String> file:///E:/FlutterProjects/daily_strength/lib/screens/DetailsView.dart:30:18
When the exception was thrown, this was the stack: 
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1      _DetailsViewState.build.<anonymous closure> 
(package:daily_strength/screens/DetailsView.dart:47:34)
#2      _FutureBuilderState.build 
(package:flutter/src/widgets/async.dart:751:55)
 #3      StatefulElement.build 
(package:flutter/src/widgets/framework.dart:4744:28)
#4      ComponentElement.performRebuild 
(package:flutter/src/widgets/framework.dart:4627:15)

Please what does this mean? I am getting the data but setting it to a text widget is not working for some reason? Thanks.

Solution

You are trying to decode the JSON when it’s not loaded. Added some comments for explanation.

if(!snapshot.hasData) {
  // Problem is here, Data has not arrived yet. You are just printing there is
  // no data, but still moving on the next step
  print('no data');
} else {
  print('hd');
}
// data is null right now, toString() just return 'null' in string form
var data = snapshot.data.toString();

// null logged to console, is the future still empty at this point? yes exactly
print(data); 

// 'null' is parsed has null is returned
final parsedData = json.decode(data); 

// parsedData is null, you can't access using [], when it's null, that why exception is thrown
print('pd ${parsedData[1]}'); 

return data == null || data.isEmpty
              ? LoadingStrengths()
              : MyDataText();

Solution:

if(!snapshot.hasData) {
  return LoadingStrengths(); // return a loader when there is not data
} else {
  // Do stuff when it is loaded;
}

Answered By – Talha Balaj

Answer Checked By – Robin (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *