Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 544
BArtWell Avatar asked Feb 12 '18 08:02

BArtWell


2 Answers

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) {}
like image 176
Kaskasi Avatar answered Nov 07 '22 10:11

Kaskasi


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
    })
}
like image 29
user2340612 Avatar answered Nov 07 '22 10:11

user2340612