【问题标题】:Why does the author design localCacheBillingClient as lateinit?为什么作者将localCacheBillingClient设计为lateinit?
【发布时间】:2020-09-01 23:07:51
【问题描述】:

代码A来自项目play-billing-samples,可以看it

不知道为什么作者把localCacheBillingClient设计成lateinit,因为代码有点复杂,if (::localCacheBillingClient.isInitialized == false) {...}被调用了很多次。

我认为代码 B 可以很好地工作,对吧?

代码 A

class BillingRepository private constructor(private val application: Application) :
        PurchasesUpdatedListener, BillingClientStateListener {

     lateinit private var localCacheBillingClient: LocalBillingDb


    val subsSkuDetailsListLiveData: LiveData<List<AugmentedSkuDetails>> by lazy {
        if (::localCacheBillingClient.isInitialized == false) {
            localCacheBillingClient = LocalBillingDb.getInstance(application)
        }
        localCacheBillingClient.skuDetailsDao().getSubscriptionSkuDetails()
    }

    val inappSkuDetailsListLiveData: LiveData<List<AugmentedSkuDetails>> by lazy {
        if (::localCacheBillingClient.isInitialized == false) {
            localCacheBillingClient = LocalBillingDb.getInstance(application)
        }
        localCacheBillingClient.skuDetailsDao().getInappSkuDetails()
    }

   fun startDataSourceConnections() {
        Log.d(LOG_TAG, "startDataSourceConnections")
        instantiateAndConnectToPlayBillingService()
        localCacheBillingClient = LocalBillingDb.getInstance(application)
    }
    ...
}

代码 B

class BillingRepository private constructor(private val application: Application) :
        PurchasesUpdatedListener, BillingClientStateListener {

    private val localCacheBillingClient: LocalBillingDb by lazy {
         LocalBillingDb.getInstance(application)
    }

    val subsSkuDetailsListLiveData: LiveData<List<AugmentedSkuDetails>> by lazy {
        localCacheBillingClient.skuDetailsDao().getSubscriptionSkuDetails()
    }


    val inappSkuDetailsListLiveData: LiveData<List<AugmentedSkuDetails>> by lazy {
        localCacheBillingClient.skuDetailsDao().getInappSkuDetails()
    }

   fun startDataSourceConnections() {
        Log.d(LOG_TAG, "startDataSourceConnections")
        instantiateAndConnectToPlayBillingService()        
    }
    ...
}

【问题讨论】:

  • 不知道为什么作者喜欢使用lateinit和反射。我也会选择惰性属性。仅将 lateinit 用于外部初始化。 stackoverflow.com/q/36623177/11377112
  • 您只能猜测编写该代码的人为什么选择这种方法。我个人同意它滥用lateinit,但这是我的意见。

标签: kotlin


【解决方案1】:

Kotlin - Property initialization using "by lazy" vs. "lateinit"

我相信答案就在这个线程中,并且正好在下面。

lateinit var 可以从任何可以看到对象的地方初始化,例如从框架代码内部,单个类的不同对象可以有多个初始化场景。反过来,lazy { ... } 定义了属性的唯一初始化程序,只能通过覆盖子类中的属性来更改它。如果您希望您的属性以一种可能事先未知的方式从外部初始化,请使用 lateinit。

【讨论】:

  • 您错过了真正的答案-该答案中提出的最后一点确实是避免使用lazy 而更喜欢lateinit 的原因,就像作者在代码A 中所做的那样。基本上在代码B 中,如果从未使用过localCacheBillingClient,它将保留对application 的引用,从而在应用程序被终止时导致内存泄漏。
猜你喜欢
  • 2020-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-22
  • 2011-03-01
  • 2011-07-23
  • 2019-02-20
  • 1970-01-01
相关资源
最近更新 更多