当我尝试使用提供程序从此item(like 0 index item)中删除listview时,它从列表中删除了最后一项。当我从列表中删除最后一个元素时,成功删除了最后一个项目。我有点困惑为什么我会发生这种问题。
我在这里发布了一些代码,请检查并给出您的宝贵建议。同时在此视频上演示发生了什么问题
链接:https://drive.google.com/file/d/1UYl8Z7vEj_tZCaYzqe0VqZL2iMla5nIZ/view?usp=sharing
预期结果:每当用户按下删除按钮,然后删除该特定行(项目)。
删除方法:-这是删除方法,当用户从列表中按Delete按钮时将调用它。

Future<void> acceptdeclinerequest(String requestStatus,int requestId) async{
    String token = await CustomPreferences.getpreferences('token');
    Map<String, String> requestHeaders;
    if (token.isNotEmpty) {
      requestHeaders = {
        'Accept': 'application/json',
        'Authorization': 'Bearer ' + token
      };
    } else {
      requestHeaders = {
        'Accept': 'application/json',
      };
    }
    var reqdata = {
      "request_id":requestId.toString(),
      "status":requestStatus
    };
    print('accept request data is $reqdata');
    try
    {
      final response =
      await http.post(Connection.url + 'respond-place-request', headers: requestHeaders,body: reqdata);
      if (response.statusCode == 200) {
        Map<String, dynamic> responseJson = json.decode(response.body);
        final existingProductIndex = _items.indexWhere((prod) => prod.id == requestId);
        var existingProduct = _items[existingProductIndex];
        _items.removeAt(existingProductIndex);
        notifyListeners();
        return responseJson;
      } /*else if (response.statusCode == 500) {
        return servererrorresponse;
      }*/
    } catch (exception) {
      throw exception;
    }
  }
主窗口小部件类:这是我定义Listview小窗口的主窗口小部件类。我已经使用provider从api中获取数据,该api是用模态类编写的,以Listview填充,而Listview child widgets是单独的类RequestWidgets。在本类(class)中,我传递了rowitems数据以listview显示。
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  var connectionstatus;
  var product;
  var _isInit = true;
  var _isLoading = false;

  @override
  void initState() {
    super.initState();
  }

  @override
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    if (_isInit) {
      setState(() {
        _isLoading = true;
      });
      Provider.of<BandRequestModal>(context).getBandRequestList().then((_) {
        setState(() {
          _isLoading = false;
        });
      });
    }
    _isInit = false;
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    connectionstatus = Provider.of<ConnectivityResult>(context);
    product = Provider.of<BandRequestModal>(context, listen: false);
    // getRequestData();
    return WillPopScope(
        onWillPop: _onWillPop,
        child: Scaffold(
            key: _scaffoldKey,
            appBar: CustomAppbar(
                _scaffoldKey, Constants.requests, 100.0, filterRecord),
            endDrawer: MenuDrawer(),
            body:
                /*(connectionstatus == ConnectivityResult.wifi ||
                    connectionstatus == ConnectivityResult.mobile)
                ? */
                Consumer<BandRequestModal>(builder: (context, modal, child) {
              return !_isLoading
                  ? Container(child: LayoutBuilder(builder:
                      (BuildContext context, BoxConstraints constraints) {
                      return Container(
                        height: constraints.maxHeight,
                        child: modal.item.length > 0
                            ? ListView.builder(
                                padding:
                                    EdgeInsets.only(top: 10.0, bottom: 0.0),
                                itemCount: modal.item.length,
                                shrinkWrap: true,
//                            physics: NeverScrollableScrollPhysics(),
                                itemBuilder: (context, int i) {
                                  return RequestWidgets(data: modal.item[i]);
                                })
                            : Center(
                                child: new Text(
                                  Constants.norecordfound,
                                  style: TextStyle(
                                      fontSize: 20.0,
                                      fontWeight: FontWeight.bold),
                                ),
                              ),

//                    ],
//                  ),
                      );
                    }))
                  : Comman.loadingIndicator(Theme.of(context).primaryColor);
            })
//                : Comman.nointernetconnection(context)
//            FutureBuilder<BandRequestModal>(
//                future: Connection.bandRequestList(),
//                builder: (context, snapshot) {
//                  switch (snapshot.connectionState)
//                  {
//                    case ConnectionState.none:
//                      break;
//                    case ConnectionState.waiting:
//                      return Comman.loadingIndicator(
//                          Theme.of(context).primaryColor);
//                      break;
//                    case ConnectionState.active:
//                      break;
//                    case ConnectionState.done:
//                      if (snapshot.hasError) {
//                        return Center(
//                          child: new Text(Constants.servererror),
//                        );
//                      }else if(snapshot.data==null){
//                        return Center(
//                          child: new Text(Constants.servererror),
//                        );
//                      } else if (snapshot.data.data.length == 0) {
//                        return Center(
//                          child: new Text(
//                            Constants.norecordfound,
//                            style: TextStyle(
//                                fontSize: 20.0, fontWeight: FontWeight.bold),
//                          ),
//                        );
//                      } else {
//                        return ListView.builder(
//                            padding:
//                            EdgeInsets.only(top: 10.0, bottom: 60.0),
//                            itemCount: snapshot.data.data.length,
//                            shrinkWrap: true,
//                            physics: NeverScrollableScrollPhysics(),
//                            itemBuilder: (context, int i) {
//                              return RequestWidgets(data:snapshot.data.data[i]);
//                            });
//                      }
//                      break;
//                  }
//                }):Comman.nointernetconnection(context)
            ));
  }
子级窗口小部件类:这是listview的行项目类。在此类中,我们使用了许多小部件来显示位置数据。
class _RequestWidgetsState extends State<RequestWidgets> {
  var getData;
  var product;

  @override
  void initState() {
    // TODO: implement initState
    getData = widget.data;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    product = Provider.of<BandRequestModal>(context, listen: false);
    return Container(
//      alignment: Alignment.topLeft,
      margin: EdgeInsets.only(top: 5.0),
      child: ListTile(
//        contentPadding: EdgeInsets.zero,
        key: ObjectKey(getData),
        leading: CircleAvatar(
          radius: 30,
          backgroundColor: Colors.transparent,
          child: ClipOval(
              child: (getData.placeDetails.image != null &&
                      getData.placeDetails.image != '')
                  ? Image.network(
                      getData.placeDetails.image,
                      width: 90,
                      height: 90,
                      fit: BoxFit.cover,
                    )
                  : Image.asset(
                      Res.defaultImage,
                      width: 90,
                      height: 90,
                      fit: BoxFit.cover,
                    )),
        ),
        title: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Expanded(
                child: Text(getData.placeDetails.name,
                    style: TextStyle(
                        fontSize: 16.0,
                        fontFamily: 'Metropolis',
                        color: CustomColors.commentTitleColor))),
          ],
        ),
        subtitle: Container(
            margin: EdgeInsets.only(top: 1.0),
            child: Column(children: <Widget>[
              Container(
                margin: EdgeInsets.only(top: 1.0),
                child: Row(children: <Widget>[
                  Expanded(
                      child: Text(getData.placeDetails.address,
                          style: TextStyle(
                              fontSize: 15.0,
                              height: 1.2,
                              fontFamily: 'Metropolis',
                              color: CustomColors.commentSubtitleColor))),
                ]),
              ),
              Container(
                  margin: EdgeInsets.only(top: 15.0, bottom: 15.0),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: <Widget>[],
                  )),
              Divider(
                color: CustomColors.commentlineColor,
                thickness: 0.8,
              )
            ])),
        trailing: Row(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            GestureDetector(
              child: CircleAvatar(
                radius: 20,
                backgroundColor: Colors.green,
                child: Icon(
                  Icons.check,
                  color: Colors.white,
                ),
              ),
              onTap: () {
                acceptrejectpopup('1');

//                {
//                  print('accept data $data');
//                  Comman.hideLoading(context);
//                  Comman.showSnakBar(data['message'],context);
//                });
              },
            ),
            SizedBox(
              width: 15.0,
            ),
            GestureDetector(
              child: CircleAvatar(
                backgroundColor: Colors.red,
                child: Icon(
                  Icons.clear,
                  color: Colors.white,
                ),
              ),
              onTap: () {
//                Comman.showLoading(context);
                acceptrejectpopup('0');
                /*product.acceptdeclinerequest('0',getData.id.toString()).then((data){
                  print('decline data $data');
                  Comman.hideLoading(context);
                  Comman.showSnakBar(data['message'],context);
                });*/
              },
            )
          ],
        ),
      ),
    );
  }

  //accept and reject
  void acceptRejectRequest(String requestStatus) async {
    try {
      var response =
          await product.acceptdeclinerequest(requestStatus, getData.id);
      if (response['status'] == Constants.status_true) {
        Comman.hideLoading(context);
        Comman.showSnakBar(response['message'], context);
//        setState(() {});
      } else {
        Comman.hideLoading(context);
      }
    } catch (exception) {
      Comman.hideLoading(context);
      Comman.showSnakBar(Constants.servererror, context);
    }
  }

  //request accept/reject popup
  Future<void> acceptrejectpopup(String reqStatus) {
    return showDialog(
      context: context,
      builder: (context) => new AlertDialog(
        title: new Text('Alert!',
            style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold)),
        content: new Text(reqStatus == '1'
            ? Constants.reqAcceptmessage
            : Constants.reqRejectemessage),
        actions: <Widget>[
          new FlatButton(
            onPressed: () => Navigator.of(context).pop(),
            child: new Text(Constants.notxt),
          ),
          new FlatButton(
            onPressed: () {
              Navigator.of(context).pop();
              Comman.showLoading(context);
              acceptRejectRequest(reqStatus);
            },
            child: new Text(Constants.yestxt),
          ),
        ],
      ),
    );
  }

最佳答案

提供程序运行良好,问题是当提供程序通知消费者ListView更新子级时,但是StatefulWidget检查它们的类型相同(它们都是RequestWidget),因此它们只是自我更新(如果您不这样做)提供StatefulWidget的密钥,他们将尝试检查它们是否相同,并通过didChangeDependencies方法进行更新),但是您正在initState中更新getData var(它将仅调用一次),因此即使使用者更新了值(value)不会。像这样尝试

@override
void initState() {
  // TODO: implement initState
  //getData = widget.data; not here
  super.initState();
}

@override
void didChangeDependencies() {
  // TODO: implement initState
  getData = widget.data; //update it here
  super.didChangeDependencies();
}
另一种选择是在itemBuilder中构建窗口小部件时提供特定的密钥,以便使用者更新时对其进行相应更改。
return RequestWidgets(key: ValueKey(modal.item[i].id),data: modal.item[i]);

// Or some value unique for each item

10-07 19:52
查看更多