Skip to content
Shreyas Patil's Blog

Let your delegates auto-nullify references☠️

Cover image for Let your delegates auto-nullify references☠️

Hello Android developers 👋, In this article, we’ll explore Kotlin’s Delegated property feature to solve a common problem in Android which will help us to reduce memory leaks.

Memory management is an important thing to take into consideration while developing a good and performant application. While developing any application, a memory leak is a common problem while developing an application if we didn’t handle resources properly as per the lifecycle events.

Let me give you examples. Imagine if you have a Fragment and it has references to some properties. We need to clear the references to these fields by assigning null in onDestroyView() lifecycle method so that Fragment won’t hold references to them.


🎬 Example 1

You may have seen this snippet of code on official Android’s docs for ViewBinding 👇:

Here, you can see that we need to create two fields _binding which is a nullable backing field for non-null field binding. What’s the reason for this? Read this 👇:

Note: As this is mentioned in the official docs. Fragments outlive their views. Make sure you clean up any references to the binding class instance in the fragment’s onDestroyView() method.

In this example, we need to declare these things twice. If we forgot to clear reference in onDestroyView() then it might lead to issues. We’ll see how to solve this after some time. Till then let’s take a look at another example.


🎬 Example 2

When you have worked with RecyclerView, sometime you might have experienced a memory leak issue due to RecyclerView.Adapter even in configuration changes like a rotating screen. So for such cases, again we need to clean adapter reference in onDestroyView() lifecycle method as following 👇:

Here you can see that we finally setting RecyclerView’s Adapter as null. Alternatively, as mentioned in OR (2️⃣) comments, we can also declare mAdapter as nullable. But if we do so then we’ll need to use ? with adapter instance every time we try to access it 😫.

Here again, if we forget to set adapter as null in onDestroyView() then it might be a problem if there’s any process that tries to access the adapter.

In both examples, we used backing fields for references like _ref for every ref and nullified it in onDestroyView(). So how to avoid this repetition, make it more readable or reduce boilerplate for every Fragment/Activity or Android’s component?


💡 Solution

The Jetpack library for Lifecycle is a very powerful library by which we can develop Android lifecycle-aware components which allow us to observe the lifecycle of components and thus we can handle things accordingly. Also, Kotlin has a variety of features and the Delegated property is one of the great features. So let’s see it in action.

I read the source code of AutoClearedValue from official samples and Gabor Varadi’s article where he mentioned a bug in this implementation. So this solution is inspired by the learnings of these two references.

First of all, add these Jetpack Lifecycle Component libraries:

implementation 'androidx.lifecycle:lifecycle-common-java8:2.3.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.0'

Create a class AutoCleanedValue.kt where we’ll wrap our logic for auto-nullifying references 👇:

Let’s understand it:

Okay! This is good. Now to make it easy to access from Fragments, let’s make an extension function:

Cool! How we are going to use it? Looks like everything is settled. Let’s see in action how our Fragment will look like after using this delegate? Let’s summarize both the examples we saw in this article in a single snippet 👇:

That’s it. Looking cool 😍, isn’t it?

What we achieved?

Now, this was just for Fragment. If we need we can extend it up to Activity, Service, etc.

I hope you liked this article. Share this if you find it helpful so that it can help someone who needs it. Sharing is caring!

Thank you. Have fun! 😄


📚 References



Previous Post
Hide internal members of Kotlin Module from JVM 🔐
Next Post
👨‍🍳 Cooking Tasty code in Kotlin 🍴 — Part 2