Application Of Singleton and Delegated Properties
Let's implement the Database by learning Singleton and Delegates properties.
Let's implement the Database by learning Singleton and Delegates properties.
A simple way to create a Singleton class in Android is :
Now we know that before onCreate invoke, we will not use an instance, so the instance is always non-nullable.
This solution seems a bit weird. We need to define a property and then a function to return that property.
Do we have another way to get a similar result? Yeah, we can delegate the value of a property to another class. These are commonly known as delegated properties.
There are some common behaviors we may need in a property that would be interesting to be reused, such as lazy values or observable properties. Instead of repeatedly declaring the same code, Kotlin provides a way to delegate the code a property needs to another class. This is known as delegated property.
When we use to get or set from a property, the getValue and setValue of the delegated property are called.
The T is the type of property that is delegating its behavior. The getValue function receives a reference to the class and the metadata of the property. The setValue function also receives the value that is being assigned. If the property is immutable (Val), it will only require the getValue function. This is how the property delegate is assigned:
class Example { var p: String by Delegate() }
Standard Delegates
There exists a set of standard delegates included in the Kotlin standard library. These are the most common situations where a delegate is really useful, but we could also create our own.
Lazy
It takes a lambda that is executed the first time getValue is called, so the initialization of the property is delayed up to that moment. Subsequent calls will return the same value. This is very interesting for things that are not always necessary and/or require some other parts to be ready before this one is used. We can save memory and skip the initialization until the property is required.
By default, the evaluation of lazy properties is synchronized: the value is computed only in one thread, but all threads will see the same value. If the synchronization of the initialization delegate is not required to allow multiple threads to execute it simultaneously, pass LazyThreadSafetyMode.PUBLICATION
as a parameter to lazy()
.
If you’re sure that the initialization will always happen in the same thread as the one where you use the property, you can use LazyThreadSafetyMode.NONE
. It doesn't incur any thread-safety guarantees and related overhead.
Observable
This delegate will help us detect changes on any property we need to observe. It will execute the lambda expression we specify, every time the set function is called. So after the new value is assigned, we receive the delegated property, the old value, and the new one.
This example represents some kind of ViewModel class that is aware of my property changes and saves them to the database every time a new value is assigned.
Vetoable
This is a special kind of observable that lets you decide whether the value must be saved or not. It can be used to check some conditions before saving a value.
Storing properties in a map
One everyday use case is storing the values of properties in a map. This often comes up in applications like parsing JSON or performing other dynamic tasks. In this case, you can use the map instance as the delegate for a delegated property.
In this example, the constructor takes a map:
Delegated properties take values from this map through string keys, which are associated with the names of properties:
This also works for var
’s properties if you use a MutableMap
instead of a read-only Map
:
How to create a custom delegate
Let’s say we want, for instance, to create a non-nullable delegate that can only be assigned once. The second time it’s assigned, it will throw an exception. Kotlin library provides a couple of interfaces our delegates must implement: ReadOnlyProperty and ReadWriteProperty. The one that should be used depends on whether the delegated property is val or var.
We can create Custom Delegate Properties in Android View Binding to eliminate lateinit var in binding.
Get rid of lateinit var when using DataBinding
Lets first lets talk about Activity Binding class :medium.com
The first thing we can do is to create a class that extends ReadWriteProperty:
This delegate can work over any non-nullable type. It will receive a reference of an object of any type, and use T as the type of the getter and the setter.
Now we need to implement the methods.
The getter will return a value if it’s assigned, otherwise it will throw an exception.
The setter will assign the value if it is still null, otherwise it will throw an exception.
Now let’s create an object with a function that provides your new delegate:
Now let’s create an object of App class by using custom delegates :
var instance: App by DelegatesExt.notNullSingleValue()
That's it. Thanks for reading; please don't forget to clap and follow for new articles about advanced kotlin .
Stayed Tuned…
Abstraction in the Modern world
This article will define how to use abstraction in the modern world precisely in the Kotlin world.blog.devgenius.io
Get an email whenever Dev Soni publishes.
Get an email whenever Dev Soni publishes. By signing up, you will create a Medium account if you don't already have…medium.com
Buy me a coffee