Android lint rule for immutable Kotlin data classes
When I started learning Kotlin, the first thing I noticed was the difference in declaring variables.
In Java, we need to specify a field as final
to be sure it won’t change on runtime for the same instance, But this is often not used. Final fields are used when it is really necessary. But Kotlin suggests using val
over var
. This helps us to have immutable instances.
Kotlin data classes are generated with a copy
method to help us easily copy an instance with new values. With the help of the copy
method, we can create new instances without modifying the original instance.
But val
doesn’t mean a class is fully immutable. It only means the reference of the field is immutable.
List
, Map
and similar collections are immutable in Kotlin. If you need to modify a collection instance, it needs to inherit from a Mutable interface like MutableList
, MutableMap
.
Technically, we can have val list: MutableList<*>
in a class. Having any mutable collection makes this class mutable even though it is a val
field.
In the past, I have fixed some bugs caused by mutable classes and I have learned the benefit of having immutable classes and designing your architecture on top of immutable classes. Having immutable classes force us to write pure classes without any side effect to parameters.
I always check var
usage and mutable collections when I perform a code review but checking fields one by one is error-prone and I am not able to review every PRs.
That is why I created ImmutableDataClassRule
and released as a library with some other rules. https://github.com/kozaxinan/android-lints
ImmutableDataClassRule
checks Kotlin data classes for mutable variable and collection usages. If I decided to use a data class
, the results of equals
, hashCode
and toString
methods are important for me. For having more secure data flow, I need to be sure an instance won’t change its inner values in any part of the flow without creating a new instance.
NetworkLayerImmutableClassRule
checks the return type of Retrofit
interface methods. It warns us for having immutable response types in our network layer for both Kotlin and Java classes. This was a need because not every network response we have is a data class
and there are still some old parts of our app which use Java.
With the help of new lint rules, we already updated some old data classes in ImmoScout24 Android app to ensure we have robust code.
Now I can focus more on the actual logic in PR, rather than checking usage of mutability in data classes.
Happy coding :)
Thanks to Said Tahsin Dane, ashdavies ™, Francesco Noya and serap bercin for their review.