Avoiding memory leaks when using Data Binding and View Binding

In our current project we are using a lot of Data Binding and recently we have started using View Binding as well.
A little while back, we were inspired by Pierre-Yves Ricau and Emily Kager’s awesome video covering how to find and fix memory leaks with LeakCanary, so we added it to our project. We soon saw falling birds all over the place.
Memory leaks everywhere
When using Data Binding we used to add the binding as a lateinit var
to our fragment like this:
This leads to a memory leak:


LeakCanary is telling us our binding
is keeping a reference to our view (mRoot
) after the Fragment’s onDestroyView()
was called and this might lead to a memory leak.
When it comes to View Binding, Google’s own docs are actually teaching us how to do it the proper way to avoid getting memory leaks:
This technique uses an optional backing field and a non-optionalval
which is only valid between onCreateView
and onDestroyView
.
In onCreateView
the optional backing field is set and in onDestroyView
it is cleared. This fixes the memory leak!
This way of doing it is also covered in the video I mentioned earlier at this timestamp.
You might feel a bit uneasy about the double bangs !!
, but all we are saying here is that we are sure this field will not be null when we use it (in the lifecycle between onCreateView
and onDestroyView
), which is exactly the same we are saying when we use lateinit var
.
Cool, but now I have to add x lines to every fragment?
Our app has a lot of fragments and it would be quite tedious to apply this fix everywhere. A while back I found this blog post by Kirill Rozov where he talks about a small view binding delegate library he made which saves you quite some hassle/lines.
Read his blog post for the details, but using this we can now write our binding like this:
His view binding property delegate takes care of the setting and clearing of the binding at the proper time in the lifecycle, so that we don’t have to do that ourselves in every fragment.
Using another trick I learned from his examples, we can actually get rid of the whole onCreateView
method. It turns out Fragment
has a constructor that takes a reference to a layout and then inflates that layout for you in onCreateView
(has this always been there?!):
This is great for view binding, but how does this help me with data binding?
Maybe this is common knowledge, but I had an aha moment when I found out that a data binding is a view binding:
This means that everything we did in this post can be applied no matter if we are using view binding or data binding!
Please let me know if this was helpful or if you have any questions or see any mistakes or things that could be done even better.
Alternative for data binding
If you are using data binding the unbind() function is an alternative (and maybe nicer) way of doing this. Thanks to Mostafa Anter for sharing this here.