Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the author design localCacheBillingClient as lateinit?

Tags:

kotlin

The Code A is from the project play-billing-samples, you can see it.

I don't know why the author design localCacheBillingClient as lateinit, it cause the code is little complex, if (::localCacheBillingClient.isInitialized == false) {...} are invoked many times.

I think Code B can works well, right?

Code 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)
    }
    ...
}

Code 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()        
    }
    ...
}
like image 755
HelloCW Avatar asked May 16 '20 01:05

HelloCW


People also ask

What is the difference between lazy and lateInit?

Lazy initialization is one of the property Delegate-s, while late initialization requires the use of a language keyword. Lazy initialization applies only to val, and late initialization applies only to var fields. We can have a lazy field of a primitive type, but lateinit applies only to reference types.

What is the use of lateInit in Kotlin?

The lateinit keyword allows you to avoid initializing a property when an object is constructed. If your property is referenced before being initialized, Kotlin throws an UninitializedPropertyAccessException , so be sure to initialize your property as soon as possible.

How do you check if lateInit VAR is initialized?

In order to avoid this situation, Kotlin introduced a new modifier called as "lateInit". Along with this modifier, Kotlin provides a couple of methods to check whether this variable is initialized or not. Use "lateInit" with a mutable variable. That means, we need use "var" keyword with "lateInit".


1 Answers

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

I believe the answer lies in this thread and precisely below point.

lateinit var can be initialized from anywhere the object is seen from, e.g. from inside a framework code, and multiple initialization scenarios are possible for different objects of a single class. by lazy { ... }, in turn, defines the only initializer for the property, which can be altered only by overriding the property in a subclass. If you want your property to be initialized from outside in a way probably unknown beforehand, use lateinit.

like image 146
Humble Bee Avatar answered Oct 08 '22 23:10

Humble Bee