Search code examples
kotlindslrx-kotlin2

How to set Rx Action Consumer in Kotlin DSL


I am investigating the development of a Kotlin DSL for RxKotlin commands

I have something working however I would to improve my approach to setting Rx Action(s) and Consumer(s).

The Code I have currently resembles this:-

@SequenceDsl
class ExperimentalBuilder {

    companion object {
        private val emptyAction = Action { }
        private val emptyConsumer: Consumer<in Throwable> = Consumer { }
    }


    var uuid: String = ""
    var onError: Consumer<in Throwable> = emptyConsumer
    var onComplete: Action = emptyAction
    var doFinally: Action = emptyAction
    var doLoginRefreshFail: Action = emptyAction

    fun build(): Experimental = Experimental(uuid, onError, onComplete, doFinally, doLoginRefreshFail)

}

import io.reactivex.Single
import io.reactivex.functions.Action
import io.reactivex.functions.Consumer
import io.reactivex.schedulers.Schedulers

data class Experimental(
    val uuid: String,
    val onError: Consumer<in Throwable>,
    val onComplete: Action,
    val doFinally: Action,
    val doLoginRefreshFail: Action
) : Morpheme() {

    override fun execute() {

        Single.just("")
            .subscribeOn(Schedulers.single())
            .ignoreElement()
            .doOnSubscribe {disposable -> COMPOSITE_DISPOSABLE.add(disposable) }
            .doOnComplete(onComplete)
            .doOnError(onError)
            .doFinally(doFinally)
            .doAfterTerminate(doAfterTerminate())
            .subscribe()
    }
}

and I use this code as follows:-

  val experimental = Dsl().experimental {
            uuid = "09876"

            onComplete = Action {
                Log.d("EXPERIMENT", "ON COMPLETE")
                Log.d("EXPERIMENT", "ON COMPLETE")
            }

            onError = Consumer {
                    throwable -> Log.e("EXPERIMENT", "ON ERROR", throwable)
            }

            doFinally =  Action {
                Log.d("EXPERIMENT", "DO FINALLY")
            }

            doLoginRefreshFail =  Action {
                Log.d("EXPERIMENT", "DO LOGIN REFRESH FAIL")
            }
        }

        experimental.execute()

        Log.d("DSL", "what $experimental")

The code I would like to "improve" is this when setting either an Action or Consumer

  onComplete = Action {
    Log.d("EXPERIMENT", "ON COMPLETE")
    Log.d("EXPERIMENT", "ON COMPLETE")
  }

  onError = Consumer {
    throwable -> Log.e("EXPERIMENT", "ON ERROR", throwable)
  }

Is this the only method I can use to set the "onCompile" Action?

e.g. Do I have to mention "Action {}" or is there a "short-hand" version I can use to achieve the same result?


Solution

  • you could define functions like this in the DSL

    fun onComplete(onCompleteCallback: ()->Unit) {
      onComplete = Action(onCompleteCallback)
    }
    

    that could be used like this:

    onComplete {
        Log.d("EXPERIMENT", "ON COMPLETE")
        Log.d("EXPERIMENT", "ON COMPLETE")
    }
    

    i hope there won't be too many of these that need it

    often kotlin can help with SAM conversion, but that seem to only really apply for function calls, not when setting it directly and once you can define a funtion you might as well make sure the wrapping is done correctly also consider making these funtions inline