You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Provider中Consumer移除列表项后UI不更新问题求助

问题描述

点击蓝色添加按钮3次后,myList中成功添加了3个元素,终端打印也显示列表长度为3。但长按第三个卡片尝试删除时,虽然终端打印显示元素已被移除,UI却没有同步更新列表。再次长按原本第三个位置的卡片时,直接抛出范围异常:

========= Exception caught by gesture ===============================================================
The following RangeError was thrown while handling a gesture:
RangeError (index): Invalid value: Not in inclusive range 0..1: 2

UI未更新截图

完整代码

controller.dart

import 'package:flutter/cupertino.dart';

class MyController extends ChangeNotifier{
  var myList = [];

  void addItemsInList(){
    myList.add('item#${myList.length}    ');

    //todo: 1* forgot
    notifyListeners();
  }

  void removeItems(index){
    myList.removeAt(index) ;
  }
}

view.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:provider_4/controller/controller_file.dart';

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return   MaterialApp(
        home: Consumer<MyController>(
          builder: (context, snapshot, child) {
            return Scaffold(
              floatingActionButton: FloatingActionButton(
                onPressed: (){
                  Provider . of <MyController> (context, listen: false) . addItemsInList();
                  print('myList.length gives: ${snapshot.myList.length}');
                  print(snapshot.myList);
                },
                child: Icon(Icons.add),
              ),
              body:   ListView.builder(
                itemCount: snapshot.myList.length , // replace with something like  myList.length
                itemBuilder: (context, index) =>   Card(
                  child: ListTile(
                    onLongPress: () {
                      Provider . of <MyController> (context, listen: false).removeItems(index);
                      // snapshot.myList.removeAt(index);
                      print(snapshot.myList);
                    },
                    title:   Text(
                      'Title', // replace with something like myList[index].title
                      style: TextStyle(
                        fontSize: 20,
                        color: Colors.black87,
                        fontWeight: FontWeight.bold,
                      ),
                    ),

                    subtitle:   Text(
                      'Details of title above', // replace with something like myList[index].details
                      style: TextStyle(
                        fontSize: 20,
                        color: Colors.deepPurple,
                        fontWeight: FontWeight.bold,

                      ),
                    ),
                    trailing: Icon(Icons.check_circle, color: Colors.green,),
                  ),
                ),
              ),
            );
          }
        ),
    );
  }
}
解决方案
  1. 修复UI不更新问题
    核心问题是removeItems方法删除元素后没有调用notifyListeners(),导致Provider无法感知数据变化,无法通知UI重建。修改controller.dart中的方法:

    void removeItems(index){
      myList.removeAt(index);
      notifyListeners(); // 新增这行,通知UI更新数据
    }
    
  2. 解决打印旧数据的问题
    点击添加按钮后直接打印snapshot.myList会拿到旧数据,因为notifyListeners()是异步触发UI重建的。把打印逻辑移到controller的addItemsInList方法里,就能打印最新数据:

    void addItemsInList(){
      myList.add('item#${myList.length}    ');
      print('myList.length gives: ${myList.length}');
      print(myList);
      notifyListeners();
    }
    

    同时删除view中按钮点击事件里的打印代码即可。

  3. 优化列表内容绑定(可选)
    当前列表的标题和副标题是固定文本,建议绑定myList中的数据,让内容和数据对应:

    title: Text(
      snapshot.myList[index], // 使用列表中的动态数据
      style: TextStyle(
        fontSize: 20,
        color: Colors.black87,
        fontWeight: FontWeight.bold,
      ),
    ),
    

内容的提问来源于stack exchange,提问作者Saad Mansoor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:35:26