0
votes

EDIT - "When I tried to run print(snapshot.error), It gave "type int is not a subtype of type string""

I am trying to get json data from https://raw.githubusercontent.com/RahulBagdiOfficial/rto_app_flutter/master/assets/json/applyonline.json

using https request package then parsing it into json data,

I am using it to build a list using ListView.builder that if the data is null return CircularProgressIndicator and if it contain data return list

The problem is This

enter image description here

its Stuck on loading

This is my code

class ApplyOnline extends StatefulWidget {
  @override
  _ApplyOnlineState createState() => _ApplyOnlineState();
}

class _ApplyOnlineState extends State<ApplyOnline> {
  @override
  Future<List<ApplyOnlineList>> _getapplyonlinelist() async {
    var data = await http.get(
        "https://raw.githubusercontent.com/RahulBagdiOfficial/rto_app_flutter/master/assets/json/applyonline.json");
    var jsonData = json.decode(data.body);

    List<ApplyOnlineList> applyonlinelist = [];
    for (var i in jsonData) {
      ApplyOnlineList applyonlineobject =
          ApplyOnlineList(i['index'], i['string'], i['url']);
      applyonlinelist.add(applyonlineobject);
    }
    print(applyonlinelist.length);
    return applyonlinelist;
  }

  Widget customURLButton(String text, String URL, Icon icon) {
    ;
  }

  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color(0xff655ee6),
      appBar: AppBar(
        backgroundColor: Color(0xff655ee6),
        title: Text("Apply Online"),
      ),
      body: SingleChildScrollView(
        child: SizedBox(
          height: MediaQuery.of(context).size.height,
          child: FutureBuilder(
            future: _getapplyonlinelist(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.data == null) {
                return Container(
                  child: Center(
                    child: CircularProgressIndicator(),
                  ),
                );
              } if(snapshot.hasData) {
                return ListView.builder(
                  itemCount: snapshot.data.length,
                  itemBuilder: (BuildContext context, int index) {
                    return ListTile(
                      title: Text(snapshot.data[index].string),
                    );
                  },
                );
              }
            },
          ),
        ),
      ),
    );
  }
}

class ApplyOnlineList {
  final int index;
  final String url;
  final String string;

  ApplyOnlineList(this.url, this.index, this.string);
}


3
it is helpful to attach your logs along with question - SriDatta Yalla
Hello, are you sure this Function of _getapplyonlinelist() is called? from what I see it is not called, that's why you only got null, try it put it before return Scaffold() and try to print out - JEFF

3 Answers

0
votes

You should pass reference of the future since you're not accepting any params in future:

future: _getapplyonlinelist

Check all the connection state before getting into snapshot.

And for checking snapshot, You can do this way:

if(snapshot.hasData) {
// return something
} else if(snapshot.hasError) {
// play with error
}
return CircularProgressIndicator();
0
votes

The problem is, you're checking for null, and returning the widget, doing this doesn't allow the FutureBuilder to rebuild because you're not checking its connection state, so the state of the data won't update. Try this instead.

 ...
         FutureBuilder(
            future: _getapplyonlinelist(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting || !snapshot.hasData) 
              {
                return Center(
                    child: CircularProgressIndicator(),
                );
              }
                return ListView.builder(
                  itemCount: snapshot.data.length,
                  itemBuilder: (BuildContext context, int index) {
                    return ListTile(
                      title: Text(snapshot.data[index].string),
                    );
                );
              }
...

Checking the ConnectionState will let the future builder resolve the future properly.

0
votes
future: _getapplyonlinelist(),

Don't do this. This way, every time your build function is called, your Future will start over. You need to start it once and then wait for it.

In your state, outside the build method, have a variable to hold the future. Assign _getapplyonlinelist() to this variable once, probably in the void initState () method. Then use that variable in your build method. That way, no matter how often the build method is called, it will not start the Future over and over and over.

In your state class:

Future<List<ApplyOnlineList>> waitingForOnlineList;

void initState () {
  waitingForOnlineList = _getapplyonlinelist();
}

... and then in your build method:

future: waitingForOnlineList,