Google Play Billing v3 初始化purchasesList null致内购查询异常
核心根因
- 问题完全来自BillingClient的调用时序错误,和Koin单例配置、Billing Library v3本身的逻辑无关。
- 当BillingClient还未完成和Google Play服务的连接流程,也就是没有收到
onBillingSetupFinished返回BillingResponseCode.OK的回调时,直接调用queryPurchases()是拿不到有效数据的:这个同步方法不会抛出异常,只会返回空的purchasesList,所有已购状态判断都会返回false。 - 当前代码的执行路径刚好踩中了这个时序坑:
- 首次进入
SettingsFragment时,Koin初始化BillingHandler,在init块里同步调用ownsProduct()查询已购状态,此时BillingClient还没建立连接,自然拿到null的购买列表,最终doesUserOwnPremium()返回false。 - 当用户点击购买入口触发
startConnection()后,代码走到连接成功的回调分支,此时BillingClient处于isReady = true的有效连接状态,再调用ownsProduct()就能正常拉取到已购商品列表,自然能正确判定用户持有高级版权益。
- 首次进入
现存代码的额外问题
doesUserOwnPremium()仅返回init阶段赋值的ownsPremium静态变量,这个值从初始化完成后就没有任何更新逻辑,哪怕后续BillingClient连上拿到了正确的已购状态,这个变量也不会同步刷新。- BillingClient的连接流程绑定在购买按钮的点击事件上,没有在页面初始化阶段主动发起连接,导致首次进入页面时所有计费相关查询都处于无效状态。
修复步骤
- 移除
BillingHandlerinit块中无效的同步查询逻辑,删掉ownsPremium = ownsProduct()这行代码——此时BillingClient未连接,查询没有任何实际意义。 - 在
onBillingSetupFinished的连接成功回调中,同步执行已购状态查询,更新ownsPremium变量:override fun onBillingSetupFinished(billingResult: BillingResult) { if(billingResult.responseCode == BillingClient.BillingResponseCode.OK) { // 连接建立成功后再查询已购状态,保证数据有效 ownsPremium = ownsProduct() loadSKUs() } else { Toast.makeText(context,"Something went wrong, please try again!", Toast.LENGTH_SHORT).show() } } - 在
SettingsFragment拿到billingHandler实例后,不要同步读取doesUserOwnPremium()的结果就直接渲染UI,需要在BillingClient连接完成、已购状态更新后,通过回调通知Fragment刷新偏好项的启用状态,避免因为时序差拿到错误的初始值。 - 在拿到
BillingHandler实例后主动调用一次startConnection()发起连接,不要等用户点击购买按钮才触发连接流程,缩短状态就绪的等待时间。
内容的提问来源于stack exchange,提问作者Stelios Papamichail
相关产品推荐
相关产品推荐

