7

This is a straight forward question but I cannot find an answer. Is there a way to be notified when a lateinit var has been initialised in Kotlin?

I know I can check if it has been initialised with this::coolvar.isInitialized but this is not the same.

Thank you

SARose
  • 3,558
  • 5
  • 39
  • 49

2 Answers2

3

lateinit var works well only in the simplest cases when uninitialized value doesn't make sense in the context of the app, such as dependency injection or late initialization in onCreate().

What you need is a property delegate with a particular behavior. Take a look at Delegates.observable :

var coolvar by Delegates.observable("initial value") { _, old, new ->
    println("coolvar has been updated")
}
voddan
  • 31,956
  • 8
  • 77
  • 87
  • This cannot be used in an inherited class I assume? – SARose Dec 08 '17 at 23:09
  • 1
    There are no restrictions. Use it the same way as a property with custom get/set, e.i. all goes except overriding the getter/setter. – voddan Dec 09 '17 at 08:38
0

If you are using Kotlin coroutines you can handle it with delay() function. for complex scenarios. not like a direct one if the value changes call this function.

Example:

private var lateinit extractFilesThread: Deferred<Unit>

private fun init() {
  GlobalScope.async {loadData()}
  GlobalScope.async {doSomeWork()}
}

private suspend fun loadData() {
  extractFilesThread = GlobalScope.async { 
    initialFilesManager.extractDataIfNeeded() 
  }
}

private suspend fun doSomeWork() {
  GlobalScope.async {
    waitExtractFilesThread()
    startThisWork()
  }
}


private suspend fun waitExtractFilesThread() {
  while (!::extractFilesThread.isInitialized) {
    delay(HALF_SECOND_IN_MILI)
  }
  extractFilesThread.await()
}

so here you want to call startThisWork() after extractFilesThread Finished and you can't use await() only if it's already initialized, so we use delay() function, It's a suspend function so it won't block other function executions.

Moaz Rashad
  • 1,035
  • 1
  • 10
  • 16