In Kotlin, how do i define a var
that has a lazy default value ?
for example, a val
would be something like this:
val toolbarColor by lazy {color(R.color.colorPrimary)}
What i want to do is, have a default value for some property (toolbarColor
), and i can change that value for anything else. Is it possible?
EDIT: This does the partial trick.
var toolbarColor = R.color.colorPrimary
get() = color(field)
set(value){
field = value
}
Is it possible to ease this by writing
var toolbarColor = color(R.color.colorPrimary)
set(value){
field = value
}
in a way that the default value is computed lazily? At the moment it won't work because color()
needs a Context
that is only initialized later.
Lazy is mainly used when you want to access some read-only property because the same object is accessed throughout. That's it for this blog.
It is lazy and thread-safe, it initializes upon first call, much as Java's static initializers. You can declare an object at top level or inside a class or another object.
Example. In this example, we will declare a lazy variable "myName" and we could see that the call to this parts of the code will happen only once and when the value is initialized, it will remember the value throughout the application. Once the value is assigned using lazy initialization, it cannot be reassigned .
lateinit can only be used with a var property whereas lazy will always be used with val property. A lateinit property can be reinitialised again and again as per the use whereas the lazy property can only be initialised once.
You can create your own delegate method:
private class ColorDelegate<T>(initializer: () -> T) : ReadWriteProperty<Any?, T> {
private var initializer: (() -> T)? = initializer
private var value: T? = null
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value ?: initializer!!()
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
}
}
Declare in some delegate:
object DelegatesExt {
fun <T> lazyColor(initializer: () -> T): ReadWriteProperty<Any?, T> = ColorDelegate(initializer)
}
And use as follow:
var toolbarColor by DelegatesExt.lazyColor {
// you can have access to your current context here.
// return the default color to be used
resources.getColor(R.color.your_color)
}
...
override fun onCreate(savedInstanceState: Bundle?) {
// some fun code
// toolbarColor at this point will be R.color.your_color
// but you can set it a new value
toolbarColor = resources.getColor(R.color.new_color)
// now toolbarColor has the new value that you provide.
}
I think this could be a cleaner way to do, but I don't know yet (starting with kotlin few days ago). I will take a look and see if this could be done with less code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With