TheOne
TheOne

Reputation: 355

How to fill SliverList with API data

I'm building a weather forecast app in which SliverAppBar shows current weather and SliverList shows daily forecast in form of cards. I get data from DarkSky API as a Map.

I have completed the current weather part with FutureBuilder, but now I'm having a trouble finding how to fill SliverList. I tried to do it with FutureBuilder as well, but without success.

This is my code

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {

  @override
  Widget build(BuildContext context) {
    return new Scaffold(

        body: new CustomScrollView(
          slivers: <Widget>[
            new SliverAppBar(
              brightness: Brightness.dark,
              centerTitle: true,
              title: Text('Weather'),
              expandedHeight: 300,
              floating: true,
              pinned: true,
              snap: true,
              flexibleSpace: FlexibleSpaceBar(
                  background: new Container(
                child: updateCurrentWeather(), //METHOD CONSTRUCTING CONTENT OF SliverAppBar
              )),
            ),
            SliverList(
              delegate: SliverChildBuilderDelegate(
                  (context, index) => Card(
                        margin: EdgeInsets.fromLTRB(30, 3, 30, 3),
                        color: Colors.black12,
                        child: new ListTile(
                          leading: Icon(Icons.watch_later),
                          title: new Text('$index',
                              style: new TextStyle(color: Colors.white)),
                          subtitle: new Text('29 °C'),
                        ),
                      ),
                  childCount: 20),
            )
          ],
        ));
  }

  Future<Map> getWeather(String key, double lat, double lon) async {
    String apiUrl =
        'https://api.darksky.net/forecast/$key/$lat,$lon?lang=sk&units=si';
    http.Response response = await http.get(apiUrl);
    return json.decode(response.body);
  }

How can I fill the SliverList with the map I get?

Upvotes: 2

Views: 4520

Answers (2)

Ali Samawi
Ali Samawi

Reputation: 1099

You can use this code but remember to create your data model for the network response to fill the list:

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {

@override
Widget build(BuildContext context) {
    return new Scaffold(

       body: new CustomScrollView(
          slivers: <Widget>[
          new SliverAppBar(
            brightness: Brightness.dark,
            centerTitle: true,
            title: Text('Weather'),
            expandedHeight: 300,
            floating: true,
            pinned: true,
            snap: true,
            flexibleSpace: FlexibleSpaceBar(
                background: new Container(
                  child: updateCurrentWeather(), //METHOD CONSTRUCTING CONTENT OF SliverAppBar
                )),
         ),
          FutureBuilder(
           future: getWeather(
               "secret key", 37.8267, -122.4233),
           builder: (context, projectSnap) {
 //                Whether project = projectSnap.data[index]; //todo check your model
             var childCount = 0;
             if(projectSnap.connectionState !=
                 ConnectionState.done || projectSnap.hasData == null)
               childCount  = 1;
             else
               childCount = projectSnap.data.length;
             return SliverList(
              delegate: SliverChildBuilderDelegate(
                      (context, index) {
                    if (projectSnap.connectionState !=
                        ConnectionState.done) { //todo handle state
                      return CircularProgressIndicator(); //todo set progress bar
                    }
                    if (projectSnap.hasData == null) {
                      return Container();
                    }
                    return Card(
                      margin: EdgeInsets.fromLTRB(30, 3, 30, 3),
                      color: Colors.black12,
                      child: new ListTile(
                        leading: Icon(Icons.watch_later),
                        title: new Text("$index",
                            style: new TextStyle(color: Colors.white)),
                        subtitle: new Text('29 °C'), //todo set your data from response
                      ),
                    );
                  },
                  childCount: childCount),
            );
          },
        ),
      ],
    ));
}

Future<Map> getWeather(String key, double lat, double lon) async {
 String apiUrl =
    'https://api.darksky.net/forecast/$key/$lat,$lon?lang=sk&units=si';
 http.Response response = await http.get(apiUrl);
 return json.decode(response.body);
}

}

Upvotes: 7

App Loops
App Loops

Reputation: 1

it should be generic - FutureBuilder<?> then only appropriate methods will work on snapShot

Upvotes: 0

Related Questions