Flutter Streambuilder to Datatable Headings Repeated

1,287
import 'dart:async';
import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: PlayerList(),
    );
  }
}

class PlayerList extends StatefulWidget {
  @override
  _PlayerListState createState() => _PlayerListState();
}

class _PlayerListState extends State<PlayerList> {
  StreamController<List<Player>> _postsController;
  final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
  List<Player> _list = <Player>[];
  ScrollController _scrollController = ScrollController();

  int count = 0;
  var url = '';

  bool fetching = false, endReached = false;

  List data;

  Future<List<dynamic>> fetchPlayer() async {
    url =
        'https://supercoach.heraldsun.com.au/2020/api/afl/classic/v1/players-cf?embed=notes%2Codds%2Cplayer_stats%2Cpositions';
    final response = await http.get(url);
    if (response.statusCode == 200) {
      print('fetching player');
      return json.decode(response.body);
    } else {
      throw Exception('Failed to load players');
    }
  }

  Future<void> loadPlayers() async {
    await fetchPlayer().then((res) async {
      for (var model in res) {
        _list.add(Player.fromMap(model));
      }
      _postsController.add(_list);
    });
  }

  Future<void> _handleRefresh() async {
    fetching = true;
    await fetchPlayer().then((res) async {
      if (res != null) {
        for (var model in res) {
          _list.add(Player.fromMap(model));
        }

        _postsController.add(_list);
        if (res.length < 10) {
          endReached = true;
          _postsController.add(_list);
        }
      } else {
        _postsController.add(null);
      }
      fetching = false;
    });
  }

  @override
  void initState() {
    _postsController = StreamController();
    loadPlayers();
    _scrollController
      ..addListener(() {
        var triggerFetchMoreSize =
            0.9 * _scrollController.position.maxScrollExtent;

        if (_scrollController.position.pixels > triggerFetchMoreSize &&
            !fetching &&
            !endReached) {
          _handleRefresh();
        }
      });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        key: scaffoldKey,
        appBar: AppBar(
          title: Text('Exploring Players'),
        ),
        backgroundColor: Color.fromRGBO(246, 249, 255, 1),
        body: StreamBuilder<List<Player>>(
          stream: _postsController.stream,
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return Text(snapshot.error);
            }

            if (snapshot.connectionState == ConnectionState.waiting ||
                snapshot.hasData == false) {
              return Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    CircularProgressIndicator(
                        valueColor:
                            AlwaysStoppedAnimation<Color>(Colors.purple)),
                    // Loader Animation Widget
                    Padding(padding: const EdgeInsets.only(top: 20.0)),
                  ],
                ),
              );
            }

            if (snapshot.data == null || snapshot.data.length == 0) {
              return Column(
                children: <Widget>[
                  Center(child: Text("Unable to find any players"))
                ],
              );
            }

            if (snapshot.hasData) {
              return SingleChildScrollView(
                scrollDirection: Axis.vertical,
                child: SingleChildScrollView(
                  physics: ClampingScrollPhysics(),
                  scrollDirection: Axis.horizontal,
                  child: DataTable(
                    columns: [
                      DataColumn(label: Text('Photo')),
                      DataColumn(label: Text('Player')),
                      DataColumn(label: Text('Round Results')),
                      DataColumn(label: Text('Played')),
                      DataColumn(label: Text('Total Points')),
                      DataColumn(label: Text('Avg')),
                      DataColumn(label: Text('3 Rd Avg')),
                      DataColumn(label: Text('5 Rd Avg')),
                    ],
                    rows: snapshot.data
                        .map(
                          (player) => DataRow(cells: [
                            DataCell(Image.network(
                                "https://s.afl.com.au/staticfile/AFL%20Tenant/AFL/Players/ChampIDImages/XLarge2020/${player.feedId}.png?i10c=img.resize(scale_height:0.2)",
                                height: 54,
                                width: 54,
                                fit: BoxFit.fitWidth)),
                            DataCell(Column(
                              children: <Widget>[
                                Text('${player.firstName} ${player.lastName}'),
                                Text(player.position),
                                Text(player.price.toString()),
                              ],
                            )),
                            DataCell(
                              Text(player.points.toString()),
                            ),
                            DataCell(Text(player.totalGames.toString())),
                            DataCell(Text(player.totalPoints.toString())),
                            DataCell(Text(player.avg.toString())),
                            DataCell(Text(player.avg3.toString())),
                            DataCell(Text(player.avg5.toString())),
                          ]),
                        )
                        .toList(),
                  ),
                ),
              );
            }

            if (!snapshot.hasData &&
                snapshot.connectionState == ConnectionState.done) {
              return Text('No Players');
            }

            if (snapshot.connectionState != ConnectionState.done) {
              return Center(
                child: CircularProgressIndicator(),
              );
            }

            return Text('No Data');
          },
        ));
  }
}

class Player {
  final String firstName;
  final String lastName;
  final String position;
  final int price;
  final int points;
  final String feedId;
  final int totalGames;
  final int totalPoints;
  final num avg;
  final num avg3;
  final num avg5;

  Player({
    @required this.firstName,
    @required this.lastName,
    @required this.position,
    @required this.price,
    @required this.points,
    @required this.feedId,
    @required this.totalGames,
    @required this.totalPoints,
    @required this.avg,
    @required this.avg3,
    @required this.avg5,
  });

  factory Player.fromMap(Map<String, dynamic> player) {
    return Player(
      avg: player['player_stats'][0]['avg'],
      avg3: player['player_stats'][0]['avg3'],
      avg5: player['player_stats'][0]['avg5'],
      feedId: player['feed_id'],
      firstName: player['first_name'],
      lastName: player['last_name'],
      points: player['player_stats'][0]['points'],
      position: player['positions'][0]['position'],
      price: player['player_stats'][0]['price'],
      totalGames: player['player_stats'][0]['total_games'],
      totalPoints: player['player_stats'][0]['total_points'],
    );
  }
}
Share:
1,287
Boss Nass
Author by

Boss Nass

BY DAY: Alt-Rock Ninja Cowgirl at Veridian Dynamics. BY NIGHT: I write code and code rights for penalcoders.example.org, an awesome non-profit that will totally take your money at that link. My kids are cuter than yours. FOR FUN: C+ Jokes, Segway Roller Derby, NYT Sat. Crosswords (in Sharpie!), Ostrich Grooming. "If you see scary things, look for the helpers-you'll always see people helping."-Fred Rogers

Updated on December 22, 2022

Comments

  • Boss Nass
    Boss Nass over 1 year

    I am trying to work out how I can get the following data into data table, but I have really struggled, as it keeps repeating the header

    import 'dart:async';
    import 'dart:convert';
    
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    
    class PlayerList extends StatefulWidget {
      @override
      _PlayerListState createState() => new _PlayerListState();
    }
    
    class _PlayerListState extends State<PlayerList> {
      StreamController<List<Map<String, dynamic>>> _postsController;
      final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
      List<Map<String, dynamic>> _list = List();
      ScrollController _scrollController = new ScrollController();
    
      int count = 0;
      var url = '';
    
      bool fetching = false, endReached = false;
    
      List data;
    
      Future<List<dynamic>> fetchPlayer() async {
        url =
            'https://supercoach.heraldsun.com.au/2020/api/afl/classic/v1/players-cf?embed=notes%2Codds%2Cplayer_stats%2Cpositions';
        final response = await http.get(url);
        if (response.statusCode == 200) {
          print('fetching player');
          return json.decode(response.body);
        } else {
          throw Exception('Failed to load players');
        }
      }
    
      loadPlayers() async {
        fetchPlayer().then((res) async {
          res.forEach((model) => _list.add(model));
          _postsController.add(_list);
          return res;
        });
      }
    
      Future<Null> _handleRefresh() async {
        fetching = true;
        fetchPlayer().then((res) async {
          if (res != null) {
            res.forEach((model) => _list.add(model));
            _postsController.add(_list);
            if (res.length < 10) {
              endReached = true;
              _list.add(Map());
              _postsController.add(_list);
            }
          } else {
            _postsController.add(null);
          }
          fetching = false;
          return null;
        });
      }
    
      @override
      void initState() {
        _postsController = new StreamController();
        loadPlayers();
        _scrollController
          ..addListener(() {
            var triggerFetchMoreSize =
                0.9 * _scrollController.position.maxScrollExtent;
    
            if (_scrollController.position.pixels > triggerFetchMoreSize &&
                !fetching &&
                !endReached) {
              _handleRefresh();
            }
          });
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
            key: scaffoldKey,
            appBar: AppBar(
              title: Text('Exploring Players'),
            ),
            backgroundColor: Color.fromRGBO(246, 249, 255, 1),
            body: Column(children: <Widget>[
              Expanded(
                child: StreamBuilder(
                  stream: _postsController.stream,
                  builder: (BuildContext context, AsyncSnapshot snapshot) {
                    print('Has error: ${snapshot.hasError}');
                    print('Has data: ${snapshot.hasData}');
    //                print('Snapshot Data ${snapshot.data}');
                    print('Connection State ${snapshot.connectionState}');
    
                    if (snapshot.hasError) {
                      return Text(snapshot.error);
                    }
    
                    if (snapshot.connectionState == ConnectionState.waiting ||
                        snapshot.hasData == false) {
                      return Center(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: <Widget>[
                            CircularProgressIndicator(
                                valueColor: new AlwaysStoppedAnimation<Color>(
                                    Colors.purple)),
                            // Loader Animation Widget
                            Padding(padding: const EdgeInsets.only(top: 20.0)),
                          ],
                        ),
                      );
                    }
    
                    if (snapshot.data == null || snapshot.data.length == 0) {
                      return Column(
                        children: <Widget>[
                          Center(child: Text("Unable to find any players"))
                        ],
                      );
                    }
    
    //                if (snapshot.hasData == false) {
    //                  return Scaffold(
    //                    backgroundColor: Colors.white,
    //                    body: new Stack(
    //                      fit: StackFit.expand,
    //                      children: <Widget>[
    //                        // Render the Title widget, loader and messages below each other
    //                        new Column(
    //                          mainAxisAlignment: MainAxisAlignment.start,
    //                          children: <Widget>[
    //                            Expanded(
    //                              flex: 1,
    //                              child: Column(
    //                                mainAxisAlignment: MainAxisAlignment.center,
    //                                children: <Widget>[
    //                                  CircularProgressIndicator(
    //                                      valueColor: AlwaysStoppedAnimation<Color>(
    //                                          Colors.purple)),
    //                                  // Loader Animation Widget
    //                                  Padding(
    //                                      padding:
    //                                          const EdgeInsets.only(top: 20.0)),
    //                                  Text("Finding players"),
    //                                ],
    //                              ),
    //                            ),
    //                          ],
    //                        ),
    //                      ],
    //                    ),
    //                  );
    //                }
    
                    if (snapshot.hasData) {
                      return Column(
                        children: <Widget>[
                          Expanded(
                            child: Scrollbar(
                              child: ListView.builder(
                                  controller: _scrollController,
                                  physics: const AlwaysScrollableScrollPhysics(),
                                  itemCount: snapshot.data.length,
                                  itemBuilder: (context, index) {
                                    Map<String, dynamic> player =
                                        snapshot.data[index];
                                    print(snapshot.data[index]);
                                    return DataTable(columns: [
                                      DataColumn(label: Text('Photo')),
                                      DataColumn(label: Text('Player')),
                                      DataColumn(label: Text('Round Results')),
                                      DataColumn(label: Text('Played')),
                                      DataColumn(label: Text('Total Points')),
                                      DataColumn(label: Text('Avg')),
                                      DataColumn(label: Text('3 Rd Avg')),
                                      DataColumn(label: Text('5 Rd Avg')),
                                    ], rows: [
                                      DataRow(cells: [
    //                                  TableRow(children: [
                                        DataCell(Image.network(
                                            "https://s.afl.com.au/staticfile/AFL%20Tenant/AFL/Players/ChampIDImages/XLarge2020/${player['feed_id']}.png?i10c=img.resize(scale_height:0.2)",
                                            height: 54,
                                            width: 54,
                                            fit: BoxFit.fitWidth)),
                                        DataCell(Column(children: [
                                          Text(
                                              "${player['first_name']} ${player['last_name']}"),
                                          Text(
                                              "${player['positions'][0]['position']}"),
                                          Text(
                                              "${player['player_stats'][0]['price']}")
                                        ])),
                                        DataCell(Text(
                                            "${player['player_stats'][0]['points']}")),
                                        DataCell(Text(
                                            "${player['player_stats'][0]['total_games']}")),
                                        DataCell(Text(
                                            "${player['player_stats'][0]['total_points']}")),
                                        DataCell(Text(
                                            "${player['player_stats'][0]['avg']}")),
                                        DataCell(Text(
                                            "${player['player_stats'][0]['avg3']}")),
                                        DataCell(Text(
                                            "${player['player_stats'][0]['avg5']}")),
                                      ])
                                    ]);
                                  }),
                            ),
                          ),
                        ],
                      );
                    }
    
                    if (!snapshot.hasData &&
                        snapshot.connectionState == ConnectionState.done) {
                      return Text('No Players');
                    }
    
                    if (snapshot.connectionState != ConnectionState.done) {
                      return Center(
                        child: CircularProgressIndicator(),
                      );
                    }
    
                    return Text('No Data');
                  },
                ),
              )
            ]));
      }
    }