Lazy initialization
So far, we have two ways to initialize properties:
- Store the initial value at the point of definition, or in the constructor
- Define a custom getter that computes the property for each access
But what if there is a third usecase where it would be costly to initialize and we might not need to use it. For example, an heavy IO computation, network requests and database access are costly operations. If we follow the above two ways, it could make application take longer for start-up time and performing unnecessary work that is never used or not required to use it immediately.
This usecase becomes so frequent that Kotlin has added a built-in solution - lazy
.
Lazy
concept
The concept isn’t new or unique to Kotlin. Laziness could be implemented within other languages, whether or not there is built-in solution. Kotlin provides this concept using property delegation.
val iAmLazy: String by lazy { "I am lazy" }
print(iAmLazy)
Without lazy
initialization, we’d be forced to make them vars
, producing less reliable code.
class LazyInt(val init: () -> Int) {
private var iAmLazy: Int? = null
val value: Int
get() {
if (iAmLazy == null)
iAmLazy = init()
return iAmLazy!!
}
}
val later = LazyInt {
print("hi")
100
}
// first time call
print(later.value) // hi 100
print(later.value) // 100
Conclusion
It is true that sometimes we need to construct the properties that could be costly for initialization. Often, we could not be sure that property will be used in the program at all. This concept of lazy
initialization was designed to prevent unnecessary initialization.