35

Disposing on Android. The right way

 5 years ago
source link: https://www.tuicool.com/articles/hit/uYRNzm2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
umeMV3a.jpg!web

Introduction

The problem is more than well known: Every Android project that is using rxJava will at some time want to subscribe to data in one of the frameworks main classes like Activity or Fragment. Obviously, those classes are created and destroyed by the Android framework itself and therefore come with a given Lifecycle . Subscriptions to streams need to be disposed at the right time in order to avoid memory leaks. This can be done very simply: Hold a reference to the Disposable when created and call the dispose function at the right moment in one of the Lifecycle hooks like onStop or onDestroy . Even though this problem is that simple, popular libraries like trello/RxLifecycle required us to load at least two artifacts and do work in some kind of BaseActivity and BaseFragment . While I admire the level of abstraction, separation and the engineering that trello’s solution offered, I am curious why all this is necessary for such a simple problem?

Why do people really need such a Library? 

Also, some of the trello/RxLifecycle’s approaches have other problems that Dan Lew, the maintainer of trello/RxLifecycle, explained well in his blog post to which I agree on.

So why?

The question is: Why have people, including myself, been using libraries like trello/RxLifecycle?

Disposing ‘by hand’ feels ugly.

This code, while perfectly functional, just feels ugly, even though it actually is not that bad. It is verbose, it is readable and clear and it is working. So why do I feel bad about it?

* Firstly *, this just breaks the aesthetics, right? You can declare almost any behavior, that you might want, inside this nice chain of operators that looks nice and compact. So all this extra code and work, even though it is not that much, just feels clunky because it is not fitting this style.

* Secondly *, this could become messy when having a more complex Activity , because it would require you to override each and every lifecycle callback to dispose the correct disposables.

* Thirdly *, this splits the definition of the stream and the information of ‘where should it be disposed’, which makes it harder to see what is going on and harder to maintain. You know when you want this subscription to be disposed when declaring the stream, so WHY should this information be spread across your activity?

All of this feelings obviously also apply when using CompositeDisposable instead of single Disposable like in the example above.

What’s wrong with trello/RxLifecycle or uber/AutoDispose ?

As previously mentioned, Dan Lew already gave us very good points on ‘ why not to use trello/RxLifecycle’ and I highly recommend reading it for more detail. Here are the points, that I value the most:

  • Automatic lifecycle detection leads to confusing and sometimes non-deterministic code.
  • trello/RxLifecycle can only simulate: It does not dispose your ‘final Disposable ’, but sends a ‘complete’ event to end the subscription which could lead to confusion or even subtle bugs.
  • It generally requires subclassing
  • It is far to complex for this simple problem. As previously mentioned: I do not want to include multiple artifacts, read lots of documentation and code to understand what is going on

The right way

Using CompositeDisposable or similar implementations to group Disposable objects and dispose them at the right time. That’s it.

So should we just ignore our feelings and concerns and accept overriding the correct lifecycle hooks is necessary to correctly dispose our subscriptions?

No! It is easy to implement some Disposer object that can make use of Android’s Lifecycle implementation to dispose automatically at the right point in time! Once this is done, nothing hinders you from extending Lifecycle to provide this Disposer automatically! And if you want: You could also easily implement those extensions for LifecycleOwner as well. Here is what you would end up with:

The code above demonstrates two possible API’s on how to declare that the stream should be automatically disposed when ‘onStop’ is called.

In order to avoid confusion, I also showed the verbose version without the extensions shortcuts.

I highly recommend avoiding to complex libraries and implement this pattern by yourself. If you like, use my implementation that I published today!

https://github.com/sellmair/disposer

Some last words

We, as programmers, often fall into the trap of thinking ‘less is more’ and confuse verbosity with the dreaded ‘Boilerplate’. Not specifying the correct point of time where Disposable objects are disposed is not even saving you time. It is literally the same amount of characters to type. It only saves us from thinking about what we are doing and I do not know why we thought it is a good idea!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK