DEV Community

Cover image for Matt's Tidbits #38 - An elegant way of dealing with RxLifecycle lint warnings
Matthew Groves
Matthew Groves

Posted on • Originally published at Medium

1 1

Matt's Tidbits #38 - An elegant way of dealing with RxLifecycle lint warnings

Last week’s tidbit described how to run apps on multiple devices simultaneously. This time my tidbit details an elegant way to handle lint warnings that arise due to using RxLifecycle.

The project I’ve been working on recently uses RxLifecycle to manage some of its observables. Curious what RxLifecycle is? In a nutshell, it’s a library that can automatically clean up asynchronous tasks — most commonly when a screen is closed, or an app is backgrounded, etc. Here’s an example of how you might use it:

class MyActivity: AppCompatActivity {
...
fun foo() {
val observable = Observable.just(true)
observable
.compose(this.bindUntilEvent(ActivityEvent.PAUSE))
.subscribe(
{ value -> Timber.d("Received value: %b", value) },
{ error -> Timber.e(error, "An error occurred") })
}
}

However, this creates lots of lint warnings scattered throughout the code:

Lint warning when result of subscribe is not used

What are our options for resolving this? We could add a @SuppressLint(“CheckResult”) annotation at every call site, but this might mask other unused problems that are not RxLifecycle-related, and this will also quickly litter the code with these annotations — not exactly ideal.

I tried out the following solution on my project and it’s been working well, so I wanted to share it here:

object RxLifecycleLintFix {
/**
* Function to help silence "result of subscribe not used" lint warnings due to using RxLifecycle
* @param disposable - the disposable produced by subscribing to RxLifecycle that we want to ignore warnings for
*/
@Suppress("UNUSED_PARAMETER")
fun ignoreRxLifecycleLint(disposable: Disposable) {
}
}
fun foo() {
val observable = Observable.just(true)
ignoreRxLifecycleLint(
observable
.compose(this.bindUntilEvent(ActivityEvent.PAUSE))
.subscribe(
{ value -> Timber.d("Value: %b", value) },
{ error -> Timber.e(error) })
)
}

This way, we no longer need all of the @SuppressLint statements for every place we use RxLifecycle. I can think of several additional benefits of this approach:

  1. Newcomers (who perhaps aren’t familiar with RxLifecycle) will be less confused by this than dangling subscribe() calls.
  2. You could add log statements/breakpoints inside of this method to easily interact with every place that uses RxLifecycle.
  3. Using a dedicated (empty) static object for this method helps keep it separate from the rest of your code.

Are there other options for how to resolve this? Of course! Here are some other ideas I considered:

  1. Removing RxLifecycle and relying on more modern frameworks (MVVM, LiveData, etc. — these can help manage asynchronous tasks in a more elegant/automatic way.
  2. Submitting a pull request against RxLifecycle that defines a custom lint rule that prevents a lint warning from appearing if you are using RxLifecycle properly — similar to this library except with logic to hide the default “result of subscribe is not used” warning: https://github.com/vokal/Android-Lint-Checks

How have you handled RxLifecycle lint warnings in your project? Let me know in the comments below! And, please follow me on Medium if you’re interested in being notified of future tidbits.

This tidbit was discovered on October 11, 2019.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay