With using brackets comes great responsibility — how I lost few hours because of using wrong type of parenthesis

I don’t know how you write your RxJava code in Kotlin (no only RxJava actually), but I’m using lambdas pretty extensively. They make the code more readable and concise, code reviews are more pleasant and digestible for your colleagues — basically, it’s hard to find any downsides.

After using them for a while putting everything in { } is very natural, sometimes (unfortunately) it comes without any second thoughts. Because of such habit recently I’ve fallen into a trap that I want to briefly describe here, to save some debugging time for future generations.

While romancing with the MVI (Model-View-Intent) on Android, you have to strongly rely on the RxJava library as the whole unidirectional flow is modeled in a reactive manner.
I won’t be focusing on the principles of this architecture in this post, but I want to show one small pitfall I personally fell into.

Let’s imagine a simple scenario — you make an API call to some backend and while the request is processing you want to display progress, sounds familiar, right?

In MVP you would normally show the progress before making the call and then hide it in some API callback like onSuccess or onError. In MVI we tackle such issue differently — we use the startWith operator in which we pass an object that represents the progress state.
Let’s dive into a snippet that will present such scenario (super simplified!)

intentSubject represents an intent which in MVI is any action performed by the user and transformed into observable for example clicking on the register button.apiSubject simulates the reactive API interface.

I decided to show this in the form of the tests as it’s pretty straightforward and shows the problem nicely.

➡️Check our Privacy Policy⬅️

In the first test we have an intent that is flatMapped into the api call. Api call chain has a startWith operator with normal parenthesis () and it’s pushing RegistrationInProgress state.

In test observer, we check if proper values were present at certain indexes, first RegistrationInProgress and then RegistrationSucces. The test passes, everything is fine.

In the second one, the only difference is that instead of using normal parenthesis ( ) we are using brackets { } with the startWith operator.

The test fails with an exception:

Okay.

If such behaviour is obvious for you — congrats, for me — it wasn’t, not at first glance at least.

Let’s get into this issue a bit deeper. In the first test using ( ) we called this implementation of the startWith

We’re just passing an item that is inserted to concatArray and published immediately by just (which is exactly what we wanted).

In the second one, when we put { },we invoked different implementation of startWith

It’s almost the same but instead of the raw object we are passing the ObservableSource which in our case will never emit any item.

So basically what happens when we use { } is that the chain freezes and no values will be ever emitted because the first item in the concatArray operator is ObservableSource that never emits any item. It’s not very easy to find as no error is emitted as well.

Mind the difference and hopefully this post will save you some debugging time — I’ve already lost enough!

Read more:

--

--