首页 > 解决方案 > 从可选数据表中的列表中删除对象

问题描述

我是 FLutter 的初学者,我创建了一个应用程序,它从 api 获取玩家列表,然后按他们的位置过滤玩家列表,一切都很完美,除了一件小事,每次我选择一个玩家并添加它到 selectedPlayers 列表,然后如果我再次单击并且该播放器仍然被选中,它不能再次出现在列表中,直到我取消选择该播放器然后播放器必须再次出现,我的问题是被选中的播放器没有在列表中删除我有一个重复的问题,我正在尝试找到解决这个问题的方法

提示: int _playerID对每个Playerr都是唯一的

我的 Playerr 模型类:

class Playerr {
  //unique field
  int _playerID;
  String _firstName;
  String _lastName;
  String _position;
  String _team;
  double _price = 5;
  String rating;
  int _appearances = 0;
  int _goals = 0;
  int _assists = 0;
  int _cleanSheets = 0;
  int _redCards = 0;
  int _yellowCards = 0;
  String _image;

  Playerr(this._playerID, this._firstName, this._lastName, this._position,
      this._team,
      this.rating, this._appearances, this._goals, this._assists,
      this._cleanSheets, this._redCards,
      this._yellowCards) {

    if (_position == ("Goalkeeper")) {
      this._image = "assets/goal.png";
    } else {
      this._image = "assets/shirt" + team.toString() + ".png";
    }

    if(rating == null){
      rating = "5.000000";
      _price = 3;
    }else if((double.parse(rating) >= 6.0) && (double.parse(rating) < 7.0)){
    _price = 6;
    }else if((double.parse(rating) >= 7.0) && (double.parse(rating) < 8.0)){
      _price = 15;
    }else if(double.parse(rating) >= 8.0){
      _price = 30;
    }
    if(appearances == null){
      appearances = 0;
    }

    if(redCards == null){
      redCards = 0;
    }

    if(yellowCards == null){
      yellowCards = 0;
    }

    if(price == null){
      price = 0;
    }

    if(goals == null){
      goals = 0;
    }else if(goals>=5 && goals < 10){
      price+=5;
    }else if(goals>=10 && goals <20){
      price+=10;
    }else if(goals>=20){
      price+=20;
    }
    if(assists == null){
      assists = 0;
    }else if(assists >= 5 && assists <10){
      price+=5;
    }else if(assists >= 10 && assists <20){
      price+=10;
    }else if(assists >= 10){
      price+=20;
    }

    if(cleanSheets == null){
      cleanSheets = 0;
    }else if(cleanSheets >= 30){
      price+=15;
    }

  }

  factory Playerr.fromJson(Map<String, dynamic> json) {
    return Playerr(int.parse(json['player']['id']), json['player']['firstname'], json['player']['lastname'],
     json['statistics'][0]['games']['position'],
     json['statistics'][0]['team']['name'],
        json['statistics'][0]['games']['rating'],
        int.parse(json['statistics'][0]['games']['appearances']),
        int.parse(json['statistics'][0]['goals']['total']),
         int.parse(json['statistics'][0]['goals']['assists']), int.parse(json['statistics'][0]['goals']['saves']),
        int.parse(json['statistics'][0]['cards']['yellow']), int.parse(json['statistics'][0]['cards']['red']));
  }

  Playerr.empty() {
    this.image = "assets/shirt_blank.png";
    this.firstName = "firstname";
    this.lastName = "lastname";
  }

  String get image => _image;

  set image(String value) {
    _image = value;
  }

 

  int get yellowCards => _yellowCards;

  set yellowCards(int value) {
    _yellowCards = value;
  }

  int get redCards => _redCards;

  set redCards(int value) {
    _redCards = value;
  }

  int get cleanSheets => _cleanSheets;

  set cleanSheets(int value) {
    _cleanSheets = value;
  }

  int get assists => _assists;

  set assists(int value) {
    _assists = value;
  }

  int get goals => _goals;

  set goals(int value) {
    _goals = value;
  }

  
  int get appearances => _appearances;

  set appearances(int value) {
    _appearances = value;
  }
  

  
  double get price => _price;

  set price(double value) {
    _price = value;
  }


  String get team => _team;

  set team(String value) {
    _team = value;
  }

  String get position => _position;

  set position(String value) {
    _position = value;
  }

  String get lastName => _lastName;

  set lastName(String value) {
    _lastName = value;
  }

  String get firstName => _firstName;

  set firstName(String value) {
    _firstName = value;
  }

  int get playerID => _playerID;

  set playerID(int value) {
    _playerID = value;
  }

  String get fullName => _firstName + " " + _lastName;
}

这里的屏幕截图显示了我所做的

在此处输入图像描述

在此处输入图像描述

在我选择了列表中的第一个玩家之后

我去选择另一个玩家,我仍然发现他没有被删除,

在此处输入图像描述

这意味着我有重复的玩家,我需要确保当他被选中时我没有任何玩家的副本,并且我还需要确保在玩家被删除后他会回到列表中。被替换,不再在 selectedPlayers 中,

这里是api的完整代码以及玩家的选择和过滤:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:footyappp/Fantazyy/Playerrs.dart';
import 'package:footyappp/Fantazyy/club_api.dart';
import 'package:footyappp/Fantazyy/create_team_view.dart';
import 'package:footyappp/Fantazyy/player%20copy.dart';
import 'package:footyappp/Fantazyy/player_lab.dart';
import 'package:footyappp/Key/Key.dart';
import 'package:http/http.dart' as http;

class PlayersCreationDetailsView extends StatefulWidget {

  final List<Playerr> selectedPlayers;
  final int playerIndex;

  const PlayersCreationDetailsView ({
    Key key,
    @required this.selectedPlayers,
    @required this.playerIndex
  })  : super(key: key);

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


class _PlayersCreationDetailsViewState extends State<PlayersCreationDetailsView> {
  bool _sortAsc = false;
  int _sortColumnIndex = 0;
  double _columnWidth  = 40.0;
  double _columnNameWidth  = 60.0;
  double _columnPosWidth  = 80.0;
  PlayersDataSource _playersDataSource;
  List<Playerr> _players = [];
  List<ClubApi> selectedClubs = [];
  List<int> clubIdentifiers = [];
  List<Playerrs> playersjson = [];
  List<Playerr> playersApi = [];
    List<dynamic> playerList ;
   List _table;


  int _rowsPerPage = 20;
   final String apiUrl =
      "https://v3.football.api-sports.io/players?season=2020&league=39";
  
  static const headers = {
    'x-rapidapi-host': "v3.football.api-sports.io",
    //Always make sure to check the api key and the limit of a request in a free api
    'x-rapidapi-key': "f6ebead51a2ade65b73948c623b1da95"
  };

  void _sort<T>(Comparable<T> getField(Playerr p), int columnIndex, bool ascending) {
    _playersDataSource._sort<T>(getField, ascending);
    setState(() {
      _sortColumnIndex = columnIndex;
      _sortAsc = ascending ;
    });
  }


  Future<void> getClubIds() async {
    http.Response response = await http.get(
        "https://v3.football.api-sports.io/teams?season=2020&league=39",
        headers: {'x-rapidapi-host': "v3.football.api-sports.io",
          'x-rapidapi-key': ApiKey.key});
    String body = response.body;
    var data = jsonDecode(body);
    List<dynamic> table = data['response'];

    setState(() {
      selectedClubs = table
          .map((dynamic item) => ClubApi.fromJson(item))
          .toList();

      for(var item in selectedClubs){
         clubIdentifiers.add(item.team.id);
      }

      for(var item in clubIdentifiers){
        print("club id"+item.toString());
        this.getPlayer(item);
      }

    });

  }


  Future<void> getPlayer(int id) async {
    http.Response response = await http.get(
      "https://v3.football.api-sports.io/players?season=2020&league=39&team=$id",
        headers: {'x-rapidapi-host': "v3.football.api-sports.io",
    'x-rapidapi-key': ApiKey.key});
    String body = response.body;
    var data = jsonDecode(body);
    List<dynamic> table = data['response'];

    setState(() {
      playersjson = table
          .map((dynamic item) => Playerrs.fromJson(item))
          .toList();

      for(var item in playersjson){
        String pos = item.statistics[0].games.position.toString().substring(8);
        playersApi.add(Playerr(item.player.id,item.player.firstname, item.player.lastname, pos,
            item.statistics[0].team.name,item.statistics[0].games.rating, item.statistics[0].games.appearences,item.statistics[0].goals.total,
            item.statistics[0].goals.assists,item.statistics[0].goals.conceded,
            item.statistics[0].cards.red, item.statistics[0].cards.yellow));
      }
      print(playersApi.length);
      // for(var item in playersApi){
      //   print("position"+item.position.toString());
      // print(item.position.contains("DEFENDER"));
      // }
      for(var item in playersApi){
        print("position"+item.position.toString());

      }
      if (widget.playerIndex < 2) {
        _players = playersApi.where((player) => player

            .position.contains("GOALKEEPER")).toList();
      } else if (widget.playerIndex < 7) {
        _players = playersApi.where((player) => player.position.contains("DEFENDER")).toList();
      } else if (widget.playerIndex < 12) {
        _players = playersApi.where((player) => player.position.contains("MIDFIELDER")).toList();
      } else {
        _players = playersApi.where((player) => player.position.contains("ATTACKER")).toList();
      }
      //filter out players who are already selected

        for (Playerr player in widget.selectedPlayers) {
          _players.remove(player);
        }
        _playersDataSource = PlayersDataSource(widget.playerIndex, widget.selectedPlayers, _players, context);

    });

  }

@override
  void initState() {
  super.initState();
  this.getClubIds();
    //filter out players by position

  }

  @override
  Widget build(BuildContext context) {
    print(playersApi.length);

    return  playersApi.length == 0
        ? Container(
      color: Colors.white,
      child: Center(
        child: CircularProgressIndicator(
          valueColor: AlwaysStoppedAnimation<Color>(
            Color(0xFFe70066),
          ),
        ),
      ),
    )
        : WillPopScope(
      onWillPop: () async => false,
      child: Scaffold(
        body: ListView(
          children: <Widget>[
            PaginatedDataTable(
              columnSpacing: 1.0,
              horizontalMargin: 1.0,
              availableRowsPerPage: [10,20,50],
              rowsPerPage: _rowsPerPage,
              onRowsPerPageChanged: (int value) { setState(() { _rowsPerPage = value; }); },
              sortColumnIndex: _sortColumnIndex,
              sortAscending: _sortAsc,
              header: Text("Players"),
              columns: <DataColumn>[
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: Text("First Name", softWrap: true,)),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<String>((Playerr p) => p.firstName, columnIndex, ascending)
                ),
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: Text("Last Name", softWrap: true,)),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<String>((Playerr p) => p.lastName, columnIndex, ascending)
                ),
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: Text("Position", softWrap: true,)),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<String>((Playerr p) => p.position, columnIndex, ascending)
                ),
                  new DataColumn(
                    label: new Container(width: _columnPosWidth , child: new Text("Price")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Playerr p) => p.price, columnIndex, ascending)
                ),
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: Text("Rating", softWrap: true,)),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<String>((Playerr p) => p.rating, columnIndex, ascending)
                ),
               /* new DataColumn(
                    label: new Container(width: _columnWidth , child: new Text("Position")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<String>((Playerr p) => p.position, columnIndex, ascending)
                ),*/
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: new Text("Team")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<String>((Playerr p) => p.team, columnIndex, ascending)
                ),
                
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: new Text("Apps")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Playerr p) => p.appearances, columnIndex, ascending)
                ),
              
               /* new DataColumn(
                    label: new Container(width: _columnWidth , child: new Text("Points")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Player p) => p.points, columnIndex, ascending)
                ),
                new DataColumn(
                    label: new Container(width: _columnWidth , child: new Text("Week Points")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Player p) => p.pointsWeek, columnIndex, ascending)
                ),*/
               
               /* new DataColumn(
                    label: new Container(width: _columnWidth , child: new Text("Sub Apps")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Player p) => p.subAppearances, columnIndex, ascending)
                ),*/
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: new Text("Goals")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Playerr p) => p.goals, columnIndex, ascending)
                ),
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: new Text("Assists")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Playerr p) => p.assists, columnIndex, ascending)
                ),
                
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: new Text("Clean")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Playerr p) => p.cleanSheets, columnIndex, ascending)
                ),
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: new Text("Yellows")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Playerr p) => p.yellowCards, columnIndex, ascending)
                ),
                new DataColumn(
                    label: new Container(width: _columnPosWidth , child: new Text("Reds")),
                    numeric: true,
                    onSort: (int columnIndex, bool ascending) => _sort<num>((Playerr p) => p.redCards, columnIndex, ascending)
                ),
               
              ],
              source: _playersDataSource,
            )
          ],
        )
      )
    );
  }
}

class PlayersDataSource extends DataTableSource {

  PlayersDataSource(this._playerIndex, this._selectedPlayers, this._players, this.context);

  int _playerIndex;
  List<Playerr> _players;
  List<Playerr> _selectedPlayers;

  int _selectedCount = 0;
  var context;
  double _columnWidth  = 40.0;
  double _columnNameWidth  = 60.0;
  double _columnPosWidth  = 80.0;

  void _sort<T>(Comparable<T> getField(Playerr p), bool ascending) {
    _players.sort((Playerr a, Playerr b) {
      if (!ascending) {
        final Playerr c = a;
        a = b;
        b = c;
      }
      final Comparable<T> aValue = getField(a);
      final Comparable<T> bValue = getField(b);
      return Comparable.compare(aValue, bValue);
    });
    notifyListeners();
  }

  DataCell getCell(String text) {
    return DataCell(Container(width: _columnPosWidth, child: Text(text, overflow: TextOverflow.fade, softWrap: false,)));
  }

  


  @override
  DataRow getRow(int index) {
    assert(index >= 0);
    if (index >= _players.length)
      return null;
    final Playerr player = _players[index];
    return DataRow.byIndex(
      onSelectChanged: (bool) {
        _players.removeAt(index);
        _selectedPlayers[_playerIndex] = player;
        Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) {return CreateTeamView(players: _players, selectedPlayers: _selectedPlayers,);}));
      },
        index: index,
        cells: <DataCell>[
          getCell(player.firstName),
          getCell(player.lastName),
          getCell(player.position),
         getCell('${player.price}'),
          getCell('${player.rating}'),
         // getCell('${player.isFresher}'),
          getCell('${player.team}'),
          //getCell('${player.points}'),
         // getCell('${player.pointsWeek}'),
          getCell('${player.appearances}'),
         // getCell('${player.subAppearances}'),
          getCell('${player.goals}'),
          getCell('${player.assists}'),
          getCell('${player.cleanSheets}'),
         // getCell('${player.motms}'),
          getCell('${player.yellowCards}'),
          getCell('${player.redCards}'),
        //  getCell('${player.ownGoals}'),
        ]
    );
  }

  @override
  int get rowCount => _players.length;

  @override
  bool get isRowCountApproximate => false;

  @override
  int get selectedRowCount => _selectedCount;


}

我真的很困惑和困惑,仍然让我感到困惑,玩家来自api json并且根本没有重复,我在这里谈论api列表不能再次显示已经选择并推送到的玩家selectedPlayers 但当玩家不在 selectedPlayers 列表中时,它必须再次显示。任何帮助都会非常有用和感激

提示: 文件CreateTeamView是 UI 长度为 16 的文件(上图中的体育场),每次点击任何索引时,上面的代码只是球员数据表的代码,每次都会调用,问题是我不希望列表每次都包含所有相同的玩家,我需要通过删除列表 selectedPlayers 包含的所有玩家来使_players 自行过滤,我搜索的第二件事是当我替换一个存在于 selectedPlayers 列表中的玩家:我想让它回到 _players 列表中,我希望这很清楚,我知道很难理解我的目标

标签: flutterdart

解决方案


我需要通过删除列表 selectedPlayers 包含的所有玩家来使 _players 自行过滤

我注意到你已经给出了int _playerID is unique for every Playerr我们可以利用它来删除项目_players

if(!_selectedPlayers.isEmpty){
_selectedPlayers.forEach((selectedPlayer) =>
          _players.removeWhere((player) => player.playerID == selectedPlayer.playerID));
}

每次进行 API 调用时,您都可以调用上述代码。

当我替换 selectedPlayers 列表中存在的播放器时:我想让它回到 _players 列表

我不认为这现在会成为问题,因为您正在从_players基础中删除播放器,selectedPlayers但如果仍然存在问题,则在替换期间,只需将旧播放器添加到列表中

_players.add(_replacedPlayer);

并且您可以通过在分配新玩家之前将存在的玩家存储在该索引中来获取被替换的玩家

_replacedPlayer = _selectedPlayers[_playerIndex];
_selectedPlayers[_playerIndex] = player;
_players.add(_replacedPlayer);

过时的

只需_isSelectedField在您的Playerr模型中有一个并创建一个 getter 函数和 setter 函数isSelectedField()并将其初始化为false您的getPlayer()函数setState(),因为最初没有选择任何玩家

 bool _isSelectedField;
 bool get isSelectedField => _isSelectedField;

 set isSelectedField (bool value) {
   _isSelectedField = value;
 }

this 的值会根据DataRow's onSelectChanged回调中的值而变化,因此您可以接受其中的值onSelectChanged并将其设置为该值。

      onSelectChanged: (bool value) {
        player.isSelectedField = value;
        _selectedPlayers[_playerIndex] = player;
        Navigator.pushReplacement(context, MaterialPageRoute(builder: (BuildContext context) {return CreateTeamView(players: _players, selectedPlayers: _selectedPlayers,);}));
      },

在你DataRow getRow(int index)和另一个 if 语句中

...

 DataRow getRow(int index) {
    assert(index >= 0);
    if (index >= _players.length)
      return null;
    final Playerr player = _players[index];
    if (!player.isSelectedField)
      return null;
...

推荐阅读