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

如何等待购买对话框弹出,以正确控制_isLoading变量状态?

Flutter IAP iOS端_isLoading提前置为false的问题解决

问题原因

iOS平台上,buyConsumable方法会在系统购买对话框弹出后立即返回Future,而非等待用户完成购买操作。这就导致你的代码中await之后的setState(() => _isLoading = false)会在对话框弹出瞬间执行,不符合你需要等待对话框弹出后再关闭加载的预期。

解决方案

不要依赖buyConsumable的Future完成时机来控制_isLoading,而是通过监听IAP的购买状态流(purchaseUpdatedStream),在收到购买处于pending状态的回调时,再将_isLoading置为false。

代码示例

首先,在初始化阶段监听购买状态流:

StreamSubscription<List<PurchaseDetails>>? _purchaseSubscription;

@override
void initState() {
  super.initState();
  _purchaseSubscription = _iap.purchaseUpdatedStream.listen((purchaseDetailsList) {
    _handlePurchaseUpdates(purchaseDetailsList);
  }, onDone: () {
    _purchaseSubscription?.cancel();
  }, onError: (error) {
    // 处理错误
  });
}

void _handlePurchaseUpdates(List<PurchaseDetails> purchaseDetailsList) {
  for (var purchase in purchaseDetailsList) {
    if (purchase.status == PurchaseStatus.pending) {
      // iOS端购买对话框已弹出,关闭加载状态
      setState(() => _isLoading = false);
    }
    // 这里还可以处理其他状态,比如purchased、error等
  }
}

@override
void dispose() {
  _purchaseSubscription?.cancel();
  super.dispose();
}

然后修改购买按钮的点击逻辑:

void _onBuyPressed() async {
  setState(() => _isLoading = true);
  try {
    await _iap.buyConsumable(
      purchaseParam: PurchaseParam(productDetails: product),
    );
  } catch (e) {
    // 如果调用buyConsumable直接失败,也要关闭加载状态
    setState(() => _isLoading = false);
    // 处理购买启动失败的错误
  }
}

说明

  • 当调用buyConsumable后,iOS系统弹出购买对话框,此时purchaseUpdatedStream会收到一条PurchaseStatus.pending的状态,这时我们关闭加载状态,符合你的流程预期。
  • 额外增加了try-catch包裹buyConsumable,避免因购买启动失败(比如产品不存在)导致加载状态一直保持true的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 08:34:57