Android lint rule for immutable Kotlin data classes

Sinan Kozak
3 min readApr 6, 2020

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.

--

--

Sinan Kozak

Staff Android Engineer at Delivery Hero in Infra team. Making sure food delivery applications won't crash and run butter smooth.