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

Flutter中API调用产生数据变更后如何刷新当前页面UI

问题根因

你的购物车操作后UI不刷新是三个代码逻辑错误导致的:

  • updateCart方法内调用fetchCartDetailsList()是异步网络请求,但你没有等待请求返回最新数据就直接执行setState,此时拿到的还是修改前的旧缓存数据
  • 你将updateCart方法定义在build方法内部,且所有通过Provider获取数据的位置都设置了listen: false,页面无法感知Provider内的数据变化
  • 删除操作的执行时序混乱:点击确认删除按钮后,删除请求刚发起就直接关闭了确认弹窗,没有等待接口返回成功结果就执行后续逻辑,容易出现状态不同步
  • 额外隐患:itemCount直接取cartDetailsList.elementAt(0).cartgrid!.length没有做空判断,购物车为空时会直接抛出数组越界错误
修复方案
  1. 将updateCart、数据获取逻辑移到build方法外,作为状态类的成员方法,所有异步请求前加await等待执行完成再刷新UI
  2. 调整删除操作的执行顺序:等待删除接口返回成功结果后,再弹出操作成功提示、拉取最新购物车数据
  3. 页面初始化外的其他位置获取Provider数据时,不要强制设置listen: false,确保数据变更能触发页面重绘
  4. 补充空安全判断,避免购物车为空时页面崩溃
修正后核心代码
class CartPage extends StatefulWidget{
  @override
  _CartPageState createState()=>_CartPageState();
}

class _CartPageState extends State<CartPage>{
  TextEditingController dateinput = TextEditingController();
  bool isLoading=true;
  String imageurl="http://192.168.10.8/DigicatDemo/Upload/Images/1/";
  late CartVM cartVM;
  List<CartdetailsModel> cartDetailsList = [];

  // 拉取购物车数据方法移到类成员位置,等待请求完成再更新状态
  Future<void> fetchData()async{
    setState(() {
      isLoading = true;
    });
    await Provider.of<CartDetailsVM>(context,listen: false).fetchCartDetailsList();
    if(mounted){
      setState((){
        cartDetailsList = Provider.of<CartDetailsVM>(context,listen: false).getCartDetailsList();
        isLoading=false;
      });
    }
  }

  // 更新购物车方法移到类成员位置,等待数据拉取完成再刷新
  Future<void> updateCart()async{
    await Provider.of<CartDetailsVM>(context,listen: false).fetchCartDetailsList();
    if(mounted){
      setState(() {
        cartDetailsList = Provider.of<CartDetailsVM>(context,listen: false).getCartDetailsList();
      });
    }
  }

  @override
  void initState() {
    super.initState();
    cartVM = CartVM(context);
    fetchData();
  }

  @override
  Widget build(BuildContext context) {
    return isLoading? const Center(child: CircularProgressIndicator())
        :  Scaffold(
      body: Column(
        children: [
          const SizedBox(height: 5.0,),
          Expanded(
              child:Padding(
                  padding:  const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 10.0),
                  child:SingleChildScrollView(
                    child: GridView.builder(
                        physics: const ScrollPhysics(),
                        shrinkWrap: true,
                        gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                          crossAxisCount: 5,
                          childAspectRatio: 0.75,
                          crossAxisSpacing: 10,
                          mainAxisSpacing: 10,
                        ),
                        // 补充空判断,避免购物车为空时崩溃
                        itemCount: cartDetailsList.isEmpty ? 0 : cartDetailsList[0].cartgrid?.length ?? 0,
                        itemBuilder: (BuildContext ctx, index) {
                          final currentProduct = cartDetailsList[0].cartgrid![index];
                          return GestureDetector(
                            onTap: (){},
                            child: Material(
                              elevation: 9,
                              shadowColor: Colors.red,
                              child: Container(
                                alignment: Alignment.center,
                                decoration: BoxDecoration(
                                  borderRadius: BorderRadius.circular(15),
                                ),
                                child: Center(
                                  child: Column(
                                    children: [
                                      IconButton(icon: const Icon(FontAwesome.trash),onPressed: (){
                                        showDialog(
                                            context: context,
                                            barrierDismissible: false,
                                            builder: (BuildContext dialogContext){
                                              return AlertDialog(
                                                title: const Text("Are you sure you want to delete this product"),
                                                actions: [
                                                  ElevatedButton(onPressed: () async {
                                                    // 等待删除接口返回结果
                                                    await cartVM.deleteCartProduct(product_code: currentProduct.ProductCode);
                                                    if(mounted){
                                                      // 先关闭确认删除弹窗
                                                      Navigator.of(dialogContext).pop();
                                                      // 弹成功提示
                                                      showDialog(context: context, builder: (BuildContext successContext){
                                                        return AlertDialog(
                                                          title: const Text("Success"),
                                                          content: const Text('Successfully deleted from the cart.'),
                                                          actions: [
                                                            ElevatedButton(onPressed: () async {
                                                              // 刷新购物车数据
                                                              await updateCart();
                                                              if(mounted){
                                                                Navigator.of(successContext).pop();
                                                              }
                                                            }, child: const Text("Close")),
                                                          ],
                                                        );
                                                      });
                                                    }
                                                  }, child: const Text("Yes")),
                                                  ElevatedButton(onPressed: (){
                                                    Navigator.of(dialogContext).pop();
                                                  }, child: const Text("No")),
                                                ],
                                              );
                                            });
                                      }),
                                    ],
                                  ),
                                ),
                              ),
                            ),
                          );
                        }),
                  )
              )
          ),
        ],
      ),
    );
  }
}

注意:代码中所有context操作前都加了mounted判断,避免异步请求返回时页面已经销毁导致的报错。如果你的CartDetailsVM是用ChangeNotifier实现的,在fetchCartDetailsList方法获取到最新服务端数据后,记得调用notifyListeners()通知所有监听位置更新。

内容的提问来源于stack exchange,提问作者Ajith S B

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:27:34