hotkey
hotkey

Reputation: 148021

RxKotlin: trying to add custom errors catching

I'm trying to write my own extension function for RxKotlin which would make an Observable handle a specific error type (Throwable subclass) with a handler which is passed as an argument and emit no more items.

Marble diagram would be:

--- a --- b --- c --- error : T

[   handleError<T>(handler)   ]

--- a --- b --- c --- finished
                   |
             handler(error)

I wrote the following:

public inline fun <reified E : Throwable, R> Observable<R>.handleError(
    crossinline handler: (E) -> Unit
) = onErrorResumeNext f@{
        return@f when (e) {
            is E -> { handler(e); Observable.empty() }
            else -> Observable.error(e)
        }
    }

It's working OK, but to use it I have to write, for example:

 val myObservable: Observable<SomeClass> = ...

 myObservable.handleError<IOException, SomeClass> { it.printStackTrace() }
                                       ^^^^^^^^^

I don't like it that I have to write the Observable's generic in handleError call, I'd like to avoid it.

So, is there a way to avoid explicitly specifying the second generic parameter?

I suppose, there's no way to make the compiler infer it once I specify one of generic parameters. But is there any way to rewrite handleErrors to achieve what I want?

Upvotes: 3

Views: 448

Answers (1)

Kirill Rakhman
Kirill Rakhman

Reputation: 43841

First, to specify E explictly, you could use the more verbose lambda syntax. This would look like this:

myObservable.handleError { it : IOException -> it.printStackTrace() }

Alternativly, you could add an additional parameter to help the compiler infer the type. This could look something like this:

public inline fun <reified E : Throwable, R> Observable<R>.handleError(
    typeHint: (E) -> Unit,
    crossinline handler: (E) -> Unit
) = onErrorResumeNext f@{
        return@f when (e) {
            is E -> { handler(e); Observable.empty() }
            else -> Observable.error(e)
        }
    }    

fun <T> of() : (T) -> Unit = {}

Usage:

myObservable.handleError(of<IOException>()) { it.printStackTrace() }

Upvotes: 7

Related Questions