Matt's Tidbits #91 - The power of sharing
Tags: mattstidbits, android, rxjava, tidbittuesday
Published: 2021-03-16 14:37:09

[Last week, I wrote about dashboards and celebrated 2 years of Matt's Tidbits!](https://matthew-b-groves.medium.com/matts-tidbits-90-all-about-dashboards-and-another-milestone-9695a68f0ee) This time, I want to share… about sharing!

Have you ever written code that looks like this?
{% gist https://gist.github.com/mpeng3/323156f46789f3e9e7db1331f3dd1292 %}

If so, you may have run into issues - what if a particular caller of `start()` forgets to call `stop()`, or possibly worse - calls it more than once? These types of problems are very common, especially in multi-threaded environments.

If you add on the layer of trying to incorporate reference counting with RxJava, the problem becomes even more complex. However, I recently discovered a rather magical operator - `share`.

From the documentation:
> *Returns a new `Observable` that multicasts (and shares a single subscription to) the current `Observable`. As long as there is at least one `Observer`, the current `Observable` will stay subscribed and keep emitting signals. When all observers have disposed, the operator will dispose the subscription to the current `Observable`.*

![](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/publishRefCount.o.v3.png)

What this means is that we can use this operator to cause the underlying observable to be refcounted! But, it goes beyond that - your underlying code doesn't actually have to use RxJava - we can use RxJava as a mechanism for accomplishing the refcounting, which, in my opinion, provides a slightly cleaner implementation.

Here's an example of what this could look like:
{% gist https://gist.github.com/mpeng3/5a8141bacd612f7cbe82f32c01842450 %}

The magic underlying this solution is that we're letting RxJava perform the ref-counting for us!

Walking through the code, here are the main parts:
1. Clients who want to use this would call `runSomeOperationThatStartsAndStopsAutomatically()`, subscribe to the `Completable` that is returned, and dispose it when they no longer want the operation to be running.
2. Under the hood, our manager class checks to see if the operation is already running - and if not, starts it (in a thread-safe way).
3. When the observable is created (note it is actually an Observable - RxJava does not provide the `share()` operator for `Single` or `Completable` types), we use the `.doOnSubscribe` and `.doOnDispose` operators to start/stop the underlying operation. What makes this work is the call to `share()`, which means that these side-effect methods only run once.
4. When all clients have unsubscribed, the underlying operation is stopped, `completable` is cleared out, so the next client to try to use this would start the operation up again.

This mechanism allows multiple clients to use this shared functionality and ensure it's only actually running once. One benefit to this solution is that the underlying operation could conceivably throw an error and anyone subscribed would be notified so they could react to that.

Note that this approach is still susceptible to someone forgetting to unsubscribe (therefore possibly preventing the underlying operation from shutting down) - but it's not possible for a single client to unsubscribe more than once. That's one of the main things I prefer about this pattern- it reduces the possibility of programmer error by using a more expressive API.

---

[In the spirit of sharing, you should also check out this wonderful new post on ViewModel lifecycle management by my colleague Jeff Padgett!](https://jeff-padgett.medium.com/how-to-make-viewmodel-observe-android-lifecycle-events-and-how-to-unit-test-lifecycle-events-d5be727da8d7)

---

How have you used the `share()` operator in your projects? Please share in the comments below!

Interested in working with me in the awesome Digital Products team here at Accenture? [We're hiring!](https://www.intrepid.io/careers)