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

Flutter中Provider无限执行导致列表数据无限追加问题如何解决?

问题根本原因
  • build方法会在组件状态变化时反复执行,你直接在build中调用fetchCartByUser,同时Provider.of<CartProvider>(context)默认会监听Provider的状态变化,只要Provider调用notifyListeners就会触发当前组件重绘,重绘又会再次调用fetchCartByUser,请求完成后又触发notifyListeners,最终形成死循环。
  • fetchCartByUser拉取新数据时,直接用insert往_cartItems列表中追加数据,没有先清空旧数据,所以每次调用接口都会重复插入相同的购物车数据,导致列表内容重复累加。
解决步骤

1. 调整数据请求的调用时机,不要在build方法中发请求

将请求逻辑放到initState中,确保页面初始化时仅执行一次,同时获取Provider时设置listen: false,避免监听状态变化触发不必要的重绘。
修改后的页面代码示例:

// 页面需要改为StatefulWidget
class CartPage extends StatefulWidget {
  const CartPage({super.key});

  @override
  State<CartPage> createState() => _CartPageState();
}

class _CartPageState extends State<CartPage> {
  String? phoneNumber;
  late String testString;
  bool isEmpty = false;

  @override
  void initState() {
    super.initState();
    // 初始化阶段仅执行一次请求
    final FirebaseAuth _auth = FirebaseAuth.instance;
    User? user = _auth.currentUser;
    phoneNumber = user?.phoneNumber;
    // listen设为false,不会因为Provider状态变化触发当前组件重绘
    final cartProvider = Provider.of<CartProvider>(context, listen: false);
    if(phoneNumber != null) {
      cartProvider.fetchCartByUser(phoneNumber!);
    }
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // ModalRoute需要等组件依赖初始化完成后获取,不能放在initState中
    testString = ModalRoute.of(context)!.settings.arguments as String;
  }

  @override
  Widget build(BuildContext context) {
    // build中仅获取数据,不要执行请求方法
    final cartProvider = Provider.of<CartProvider>(context);
    isEmpty = cartProvider.cartItems.isEmpty;
    
    return isEmpty
        ? Scaffold(body: CartEmpty())
        : Scaffold(
            // 你的购物车页面布局逻辑
          );
  }
}

2. 修改fetchCartByUser方法,拉取新数据前清空旧列表

避免重复插入数据,修改后的Provider代码:

Future<void> fetchCartByUser(String phoneNumber) async {
  // 先清空旧的购物车数据,防止重复累加
  _cartItems.clear();
  await Server.getCartData().then((value) {
    for(var item in value) {
      _cartItems.insert(
        0,
        CartModel(
          cartId: item['cartId'],
          clientAddress: item['clientAddress'],
          clientFullname: item['clientFullname'],
          clientPhoneNumber: item['clientPhoneNumber'],
          createdAt: item['createdAt'],
          merchant: item['merchant'],
          merchantCode: item['merchantCode'],
          price: item['price'],
          productCode: item['productCode'],
          productImage: item['productImage'],
          productName: item['productName'],
          productQty: item['productQty'],
          productSKU: item['productSKU'],
        ),
      );
    }
  });
  notifyListeners();
}

可选优化:增加请求状态锁,防止重复触发请求

如果存在多个场景可能触发购物车刷新,可以加请求状态标记,避免短时间重复调用接口:

class CartProvider with ChangeNotifier {
  List<CartModel> _cartItems = [];
  bool _isLoading = false;
  // 对外暴露加载状态,可用于页面展示加载动画
  bool get isLoading => _isLoading;

  List<CartModel> get cartItems {
    return [..._cartItems];
  }

  CollectionReference cart = FirebaseFirestore.instance.collection('cart');

  Future<void> fetchCartByUser(String phoneNumber) async {
    // 正在请求中直接返回,避免重复调用
    if(_isLoading) return;
    _isLoading = true;
    notifyListeners();
    
    _cartItems.clear();
    try {
      final value = await Server.getCartData();
      for(var item in value) {
        _cartItems.insert(0, CartModel(/* 和之前的参数一致 */));
      }
    } catch(e) {
      // 自行处理请求异常逻辑
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // 剩余的deleteSingleCart、updateProductQty、totalAmount逻辑保持不变
}

内容的提问来源于stack exchange,提问作者Amitha Mohanan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 06:45:04