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

Flutter Provider实现自定义按钮加载时显示CircularProgressIndicator

问题分析与解决方案

问题根源

你的TrustyButton组件内部通过ChangeNotifierProvider(create: (context) => OrderService())创建了一个独立的OrderService实例,而调用deleteOrderWithId方法时使用的是上层(如订单列表页面)提供的另一个OrderService实例。两个实例完全独立,删除订单时修改的是上层实例的isLoading,按钮监听的自身实例状态从未改变,因此UI没有更新。

解决方案

1. 移除按钮内部的Provider,复用上层实例

修改TrustyButton,让它直接从父级context获取已有的OrderService实例,不再自行创建:

import ...

class TrustyButton extends StatelessWidget {
  final void Function() onTap;
  final String text;
  final ButtonType type;
  final Icon? icon;

  TrustyButton({
    super.key,
    required this.onTap,
    required this.text,
    required this.type,
    this.icon,
  });

  final Map<ButtonType, Map<String, Color>> color = {...}

  @override
  Widget build(BuildContext context) {
    return Consumer<OrderService>(
      builder: (context, orderService, _) => GestureDetector(
        onTap: onTap,
        child: Opacity(
          opacity: orderService.isLoading ? 0.5 : 1,
          child: Container(
            height: 56,
            decoration: BoxDecoration(
              color: color[type]!['backgroundColor']!,
              borderRadius: const BorderRadius.all(
                Radius.circular(20),
              ),
              boxShadow: [
                BoxShadow(
                  color: const Color(0x15000000),
                  blurRadius: 10,
                  spreadRadius: 0,
                  offset: Offset.fromDirection(2, 2),
                ),
              ],
            ),
            child: Center(
              child: orderService.isLoading
                  ? const CircularProgressIndicator(
                      color: Colors.white,
                    )
                  : renderButtonContent(),
            ),
          ),
        ),
      ),
    );
  }
}

2. 确保上层已提供OrderService实例

在使用TrustyButton的页面(如订单列表页)上层,必须通过ChangeNotifierProvider提供全局/页面级的OrderService实例,示例:

class OrderListPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => OrderService(),
      child: Scaffold(
        body: // 订单列表内容
        // 使用按钮的位置
        TrustyButton(
          onTap: () {
            // 调用上层实例的删除方法,listen: false避免不必要的监听
            Provider.of<OrderService>(context, listen: false)
                .deleteOrderWithId(订单ID, context);
          },
          text: "删除订单",
          type: ButtonType.danger,
        ),
      ),
    );
  }
}

额外注意

  • 调用deleteOrderWithId时需添加listen: false,因为此处仅需执行方法,不需要监听状态变化
  • 如果你的OrderService是全局提供的(如在MaterialApp上层),页面层无需重复创建Provider,直接使用即可

内容的提问来源于stack exchange,提问作者Felix Hohn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:23:19