I'm trying to use kotlin M12 in android project and during the work I got this piece of code subscribe({onSuccess(it)}, {onFailure(it)})
AppObservable.bindActivity(this, api.get(id)).subscribe({onSuccess(it)}, {onFailure(it)})
fun onSuccess(str: String) {}
fun onFailure(tr: Throwable) {}
This is not so bad, but I think it would/should be better. How can I improve it?
The syntax of a lambda function is lambda args: expression . You first write the word lambda , then a single space, then a comma separated list of all the arguments, followed by a colon, and then the expression that is the body of the function.
A lambda expression is always surrounded by curly braces, argument declarations go inside curly braces and have optional type annotations, the code_body goes after an arrow -> sign. If the inferred return type of the lambda is not Unit, then the last expression inside the lambda body is treated as return value.
You use lambda expressions extensively in Android development and more generally in Kotlin programming.
Lambda functions are inline functions and thus execute comparatively faster.
First, create a helper extension method like this:
fun<T, R> Observable<T>.subscribe(
receiver: R,
onSuccess: R.(T) -> Unit,
onFailure: R.(Throwable) -> Unit) {
subscribe({ receiver.onSuccess(it) }, { receiver.onFailure(it) })
}
Now you can use your new method like this:
AppObservable.bindActivity(this, api.get(id)).subscribe(this, ::onSuccess, ::onFailure)
The ::
operator creates a method reference. Once KT-6947 gets resolved, we can omit the helper method and write subscribe(this::onSuccess, this::onFailure)
directly. This is already possible in Java 8.
To work around this issue we can alternatively implement the following helper method that binds a receiver to an extension method:
fun <T, R, E> T.bind(reference: T.(R) -> E): (R) -> E = { this.reference(it) }
and use it like this:
AppObservable.bindActivity(this, api.get(id)).subscribe(bind(Foo::onSuccess), bind(Foo::onFailure))
but this is hardly more elegant than your initial solution.
EDIT1:
Thy syntax ::onSuccess
is forbidden for now, so you have to use 'Foo::onSuccess' where Foo
is your class name.
EDIT2:
You can have a little fun with operator overloading by declaring the same method as
operator fun <T, R, E> T.plus(reference: T.(R) -> E): (R) -> E = { this.reference(it) }
Then you can use it like so:
AppObservable.bindActivity(this, api.get(id)).subscribe(this + Foo::onSuccess, this + Foo::onFailure)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With