BArtWell
BArtWell

Reputation: 4044

Kotlin + Rx: required Consumer, found KFunction

I am using Kotlin + Retrofit + Rx. I want to extract one of requests into function:

fun getDataAsync(onSuccess: Consumer<Data>, onError: Consumer<in Throwable>) {
    ApiManager.instance.api
            .getData("some", "parameters", "here")
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(Consumer {
                time = System.currentTimeMillis()
                onSuccess.accept(it)
            }, onError)
}


fun onButtonClick() {
    getDataAsync(this::onSuccess, this::onError)
}

private fun onSuccess(data: Data) {}

private fun onError(throwable: Throwable) {}

I get an errors in line getDataAsync(this::onSuccess, this::onError):

Type mismatch: inferred type is KFunction1<@ParameterName Data, Unit> but Consumer<Data> was expected

Type mismatch: inferred type is KFunction1<@ParameterName Throwable, Unit> but Consumer<in Throwable> was expected

How to fix it?

Upvotes: 6

Views: 3241

Answers (2)

user2340612
user2340612

Reputation: 10703

The issue is that your method getDataAsync requires an object of type Consumer for both arguments, while you are providing a method reference. Please note that the same error happens in Java.

In order to solve it you can either declare both arguments of getDataAsync as function reference, or create an implementation of Consumer.

First solution

fun getDataAsync(onSuccess: (Data) -> Unit, onError: (Throwable) -> Unit) {

}

fun onButtonClick() {
    getDataAsync(::onSuccess, ::onError)
}


private fun onSuccess(data: Data) {

}

private fun onError(throwable: Throwable) {}

Second solution

fun getDataAsync(onSuccess: Consumer<Data>, onError: Consumer<in Throwable>) {

}

fun onButtonClick() {
    getDataAsync(Consumer { data ->
        // do something
    }, Consumer { throwable ->
        // do something
    })
}

Upvotes: 3

Kaskasi
Kaskasi

Reputation: 1340

Instead of passing a Consumer as a parameter you could just pass a function

fun getDataAsync(onSuccess: (Data) -> Unit, onError: (Throwable) -> Unit) {
     ApiManager.instance.api
        .getData("some", "parameters", "here")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe({
            time = System.currentTimeMillis()
            onSuccess(it)
        }, onError)
}


fun onButtonClick() {
   getDataAsync(this::onSuccess, this::onError)
}

private fun onSuccess(data: Data) {}

private fun onError(throwable: Throwable) {}

Upvotes: 3

Related Questions