0

This is my Train Client class and getName method returns me a list of Train objects. I check it by using printing statement it worked successfully, but when I am returning I am not sure whether it's returning properly

class TrainClient {
  

  static Future<List<Train>> getName() async {

    final uri = Uri.parse("http://localhost:3000/search?from=54&to=61&date=2021-08-11");

    final response = await get(uri);



       final data = json.decode(response.body);

       final result = data["RESULTS"]["directTrains"]["trainsList"];
       final list =  result.map((json) => Train.fromJson(json)).toList();
       print("TrainClient");
       print(list);
       return list;





  }

}

Output got when I called this method

[Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train', Instance of 'Train']

But when I use a future builder here I am always getting null value, first, the screen is red, and after it changes to green and after that nothing returns. But I want DataTable to return

Here is the code of my future builder

class TimeTable extends StatefulWidget {
  final url;
  const TimeTable({Key? key,required this.url}) : super(key: key);

  @override
  _TimeTableState createState() => _TimeTableState();
}

class _TimeTableState extends State<TimeTable> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(body:FutureBuilder(
      future:TrainClient.getName() ,
      builder: (context,AsyncSnapshot<List<Train>> snapshot){
        if(snapshot.connectionState==ConnectionState.done){
          print(snapshot.data);
          if(snapshot.data != null) {
            return buildDataTable(trains: snapshot.data!);
          }
          return Container(color:Colors.green);
        }
        return Container(color: Colors.red,);
      },
    ) );

  }}

I also got snapshot.data== null when I print it. Why is that??? Why it's keep returning null

2 Answers2

1

You can try this. It also used to check whether the snapshot has error

 Widget build(BuildContext context) {
        return Scaffold<List<Train>>(body:FutureBuilder(
          future:TrainClient.getName() ,
          builder: (BuildContext context, AsyncSnapshot snapshot){
            if(snapshot.hasError){
                print(snapshot)
            } else
            if(snapshot.hasData){
                print(snapshot.data);
                return buildDataTable(trains: snapshot.data!);
            }
              return Container(color:Colors.green);
            }
            return Container(color: Colors.red,);
          },
        ) );

And define the return type in the TrainClient

return List<Train>.from(result.map((item) => Train.fromJson(item)));
Ananda Pramono
  • 899
  • 1
  • 6
  • 18
0

what about using dio for api integrations and this json converter to handle your responses? by the way. The getNamefunction will be called every time the widget is rebuilt. To avoid the function to be called every time the widget is rebuilt, you must not create the Future inside State.build or StatelessWidget.build method. You must create the future outside the future builder earlier. So create a local var _listName and int State.didChangeDependencies, or State.didUpdateWidget.

class TimeTable extends StatefulWidget {
  final url;
  const TimeTable({Key? key,required this.url}) : super(key: key);

  @override
  _TimeTableState createState() => _TimeTableState();
}

class _TimeTableState extends State<TimeTable> {
Future<List<Train>> _value;
 @override
  initState() {
    super.initState();
    _value = getName();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(body:FutureBuilder(
      future:_value ,
      builder: (context,AsyncSnapshot<List<Train>> snapshot){
        if(snapshot.connectionState==ConnectionState.done){
          print(snapshot.data);
          if(snapshot.data != null) {
            return buildDataTable(trains: snapshot.data!);
          }
          return Container(color:Colors.green);
        }
        return Container(color: Colors.red,);
      },
    ) );

  }}