null 不能转换为非 null 类型 kotlin.collections.List<com.android.billingclient.api.Purchase>

null cannot be cast to non-null type kotlin.collections.List<com.android.billingclient.api.Purchase>

我的大多数应用用户都没有遇到任何崩溃。但是,我的一些应用程序用户遇到了这个致命异常:

Fatal Exception: java.lang.NullPointerException: null cannot be cast to non-null type kotlin.collections.List<com.android.billingclient.api.Purchase>
       at com.company.appname.ActivityClass$loadAllSKUs.onSkuDetailsResponse(ActivityClass.java:10)
       at com.android.billingclient.api.zzj.run(zzj.java:7)
       at android.os.Handler.handleCallback(Handler.java:873)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:226)
       at android.app.ActivityThread.main(ActivityThread.java:7178)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:503)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:942)

这是我的代码。我用它来查看用户是否已经购买了应用内购买。如果他没有,启动计费流程。

  private lateinit var billingClient: BillingClient
  private val skuList = listOf("product")
  private boolean isOwned = false

  private fun loadAllSKUs() {
    if (billingClient.isReady)
    {
      val params = SkuDetailsParams.newBuilder()
              .setSkusList(skuList)
              .setType(BillingClient.SkuType.INAPP)
              .build()
      billingClient.querySkuDetailsAsync(params) { billingResult, skuDetailsList ->
        if (skuDetailsList != null)
        {
          if (billingResult.responseCode === BillingClient.BillingResponseCode.OK && !skuDetailsList.isEmpty())
          {
            for (skuDetailsObject in skuDetailsList)
            {
              val skuDetails = skuDetailsObject
              if (skuDetails.sku.equals("product"))
              {
                val result: Purchase.PurchasesResult = billingClient.queryPurchases(BillingClient.SkuType.INAPP)
                val purchases: List<Purchase> = result.getPurchasesList() as List<Purchase>

                for (purchase in purchases)
                {
                  val thisSKU = purchase.sku
                  if (thisSKU == "product")
                  {
                    isOwned = true;
                    // System.out.println("OWNED")
                  }
                }
               


if(isOwned == false){
                    val billingFlowParams = BillingFlowParams
                            .newBuilder()
                            .setSkuDetails(skuDetails)
                            .build()
                    billingClient.launchBillingFlow(this@ActivityClass, billingFlowParams)
}
              }
            }
          }
        }
      }
    }
  }

请告诉我如何解决这个问题,谢谢。 This question 得到同样的错误,但显然没有找到修复。

如果...

,Kotlin 比很多级联更具表现力

此外,Kollin 在编译时处理空值,因此 IDE 应该通知您是否为空。

我试图重写你的代码,因为它非常不可调试。 老实说,我不知道它是否有效以及它是否做同样的事情(它应该但正如我所说的所有那些如果很难理解)但我发现它更具可读性和可调试性。

请记住,要删除所有 if !=null,您可以使用 ?。运算符

希望它能帮助您理解 Kotlin 的表达能力

private fun loadAllSKUs() {
    billingClient.takeIf{it.isReady}
    ?.let {
    val params = SkuDetailsParams.newBuilder()
            .setSkusList(skuList)
            .setType(BillingClient.SkuType.INAPP)
            .build()
    billingClient.querySkuDetailsAsync(params) { billingResult, skuDetailsList ->
    skuDetailsList
        ?.takeIf{ billingResult.responseCode === BillingClient.BillingResponseCode.OK && skuDetailsList.isNotEmpty() }
        ?.filter {it.sku.equals("product")}
        ?.forEach { skuDetails -> 
            val result: Purchase.PurchasesResult = billingClient.queryPurchases(BillingClient.SkuType.INAPP)
            val purchases: List<Purchase>? = result.getPurchasesList() as? List<Purchase>
            val isOwned = purchases?.any { it.sku == "product" }?:false
            
            if(!isOwned){
                val billingFlowParams = BillingFlowParams
                        .newBuilder()
                        .setSkuDetails(skuDetails)
                        .build()
                billingClient.launchBillingFlow(skuDetails@ActivityClass, billingFlowParams)
                }
            }
        }
    }

如前所述,错误指向result.getPurchasesList()

的强制转换

当您的应用程序处于该状态时,您需要检查该情况并捕获有关其内容的更多数据 returns 以及原因。

至于上面的答案和 Unresolved reference: it 上的错误,要使用 takeIf,您必须传递谓词,因此您必须将这些括号更改为 {}

    billingClient.takeIf{it.isReady}?.let {

勾选https://medium.com/mobile-app-development-publication/using-kotlin-takeif-or-takeunless-c9eeb7099c22