2

(This question is asked under an Android context, but answerable with only Kotlin knowledge.)

(Also, I found some answers in SO regarding same question in Java8 Lambda, but I can't find one regarding Kotlin.)

Like many people do - I am now using RxJava with Retrofit to do network calls.
And recently I have switched to using Kotlin.

I have declared my own Observer for centralizing error handling.

This is my APIResponseObserver<T> extends Observer<T>: (Simplified)

abstract class APIResponseObserver<T> : Observer<T> {

    constructor(fragment: BaseFragment) : super(fragment)

    constructor(activity: BaseActivity) : super(activity)

    override fun onSubscribe(d: Disposable) {
        fragment?.addToCompositeDisposable(d)
        activity?.addToCompositeDisposable(d)
    }

    override fun onError(e: Throwable) {
        val fm = if (activity == null) fragment?.childFragmentManager else activity?.supportFragmentManager
        if (e is APIManager.APIException && e.message != null) {
            fm?.showSimpleTextDialog(e.message!!)
        } else {
            val errorMsg = if (activity == null) fragment?.getString(R.string.network_error) else activity?.getString(R.string.network_error)
            errorMsg?.let {
                fm?.showSimpleTextDialog(it)
            }
        }
    }

    override fun onComplete() {
    }
}

As you can see, only onNext() is not overridden.

And this is how I am using it now:

    APIManager.getSomeBoolean().subscribe(object : APIResponseObserver<Boolean>(this) {
        override fun onNext(t: Boolean) {
            if (context == null) return
            //Do something with the boolean
        }
    })

After using one week of Kotlin, the above usage really feels clumsy to me.
What I expect is using lambda like below:

    APIManager.getSomeBoolean().subscribe(APIResponseObserver<Boolean>(this) {t: Boolean
        if (context == null) return
        //Do something with the boolean
    })

So that I don't need to write object : and also override fun onNext(t: Boolean) {.

But, is this possible? If yes, how can I achieve this?

Sira Lam
  • 5,179
  • 3
  • 34
  • 68

1 Answers1

4

You can make you class non-abstract and add lamdba for observing onNext events as last parameter of your constructors:

class APIResponseObserver<T> : Observer<T> {

    private val onNextCallback: (T) -> Unit

    constructor(fragment: BaseFragment, onNext: (T) -> Unit) : super(fragment) {
       onNextCallback = onNext
    }

    constructor(activity: BaseActivity, onNext: (T) -> Unit) : super(activity) {
       onNextCallback = onNext
    }

    ... other methods ...

    override fun onNext(t: T) {
        onNextCallback.invoke(t)
    }
}

Kotlin allows to put lambda implementation outside parentheses in case if it is last argument in your method/constructor. All you need to do is to call passed lambda inside overridden onNext method.

In the end it allows you to write exactly same code that you expect:

APIResponseObserver<Boolean>(this) { t: Boolean ->
    if (context == null) return@APIResponseObserver 
    //Do something with the boolean
}
hluhovskyi
  • 9,556
  • 5
  • 30
  • 42