如何等待购买对话框弹出,以正确控制_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
相关产品推荐
相关产品推荐

