Reescriba el código de Java en Kotlin utilizando la reference de function.
Tengo un código de Java de ejemplo que utiliza la reference de método que quiero reescribir a Kotlin. La versión de Java usa la reference de método, la solución es corta y clara. Pero, por otro lado, no puedo usar la reference de método en Kotlin. La única versión que he logrado escribir es la que se presenta a continuación. Parece que Function3 { s: String, b: Boolean, i: Int -> combine(s, b, i) }
podría escribirse de una manera más limpia (si es posible, la reference del método sería perfecta).
Soy nuevo en Kotlin, así que agradeceré cualquier pista.
- Cómo get el último valor emitido de observable
- ¿Por qué no puedo usar la interfaz como el tipo genérico en este transformador Rx?
- Cambio observable a condición cumplida - RxJava2
- Solicitud en Android siempre dando exception de time de espera del socket
- rxjava2 - ejemplo simple de ejecutar tareas en un grupo de subprocesss, suscribirse en un solo hilo
Java
import io.reactivex.Observable; public class TestJava { Observable<String> strings() { return Observable.just("test"); } Observable<Boolean> booleans() { return Observable.just(true); } Observable<Integer> integers() { return Observable.just(1); } void test() { Observable.combineLatest(strings(), booleans(), integers(), this::combine); } double combine(String s, boolean b, int i) { return 1.0; } }
Kotlin
import io.reactivex.Observable import io.reactivex.functions.Function3 class TestKotlin { fun strings(): Observable<String> { return Observable.just("test") } fun booleans(): Observable<Boolean> { return Observable.just(true) } fun integers(): Observable<Int> { return Observable.just(1) } fun test() { Observable.combineLatest(strings(), booleans(), integers(), Function3 { s: String, b: Boolean, i: Int -> combine(s, b, i) }) } fun combine(s: String, b: Boolean, i: Int): Double { return 1.0 } }
EDITAR
El siguiente método de references en Kotlin da un error.
fun test() { Observable.combineLatest(strings(), booleans(), integers(), this::combine) } fun test() { Observable.combineLatest(strings(), booleans(), integers(), TestKotlin::combine) }
No se puede invocar ninguna de las siguientes funciones con los arguments suministrados: @CheckReturnValue @SchedulerSupport público final fundado combine Latest (p0: ((Observer) -> Unit) !, p1: ((Observer) -> Unit) !, p2: (( Observer) -> Unidad) !, p3: ((???, ???, ???) -> ???)!): Observable <(??? .. ???)>! definido en io.reactivex.Observable @CheckReturnValue @SchedulerSupport public open funciona combine-latest (p0: ¡ObservableSource !, p1: ObservableSource !, p2: ObservableSource !, p3: io.reactivex.functions.Function3!): Observable <(???. . ???)>! definido en io.reactivex.Observable @CheckReturnValue @SchedulerSupport abierto público fundado combine Latest (p0: Function !, out (??? .. ???)> !, p1: Int, vararg p2: ObservableSource!): Observable <(? ?? .. ???)>! definido en io.reactivex.Observable
EDIT 2
RxKotlin resuelve el problema mencionado en la respuesta.
import io.reactivex.rxkotlin.Observables class TestKotlin { fun test() { Observables.combineLatest(strings(), booleans(), integers(), this::combine) } }
- Error "No se puede combinar Dex" al usar Room + Kotlin
- kotlin consiguiendo un suscriptor para observar un observable usando RxJava2
- No se puede 'observar en' hilo principal con RxKotlin
- RxJava2 Publicado
- ¿Cómo se simula emitir 2 streams infinitas observables y tener otras observables que las fusionan y amortiguan cada 10 segundos?
- No se puede llamar al operador desde () en Observable en Android Kotlin
- RxJava2 + Retrofit pantalla negra en request de datos
- Mockito never () no funciona con andThen rxjava2
También puede usar Expresión de reference de function en Kotlin al igual que Expresión de reference de método en Java. por ejemplo, la reference de function combine
como KFunction3
en Kotlin como se muestra a continuación:
val f: kotlin.reflect.KFunction3<String, Boolean, Int, Double> = this::combine
En Java, Method Reference Expression se puede asignar a cualquier interfaz funcional compatible , pero no se puede asignar una expresión de reference de function a ningún tipo de function, incluso si son compatibles , por ejemplo:
val f:io.reactivex.functions.Function3<String,Boolean,Int,Double> =this::combine // type mismatch error ---^
De hecho, Kotlin usa las Conversiones SAM para convertir lambda / Function Reference Expression en una implementación de Java Functional Interface , lo que significa que Kotlin hace algo como lo siguiente:
fun test() = TODO() val exector:Executor = TODO() exector.execute(::test) //::test compile to java code as below: Runnable task = new Runnable(){ public void run(){ test(); } };
¿ Por qué Method Reference Expression puede funcionar bien en Java, pero al usar Function Reference Expression falla en Kotlin?
Basa en lo anterior, y puedes ver que hay muchos methods combineLatest
en rx-java2 . por ejemplo, los siguientes dos no pueden hacer que Kotlin use la Expresión de reference de function correctamente:
combineLatest( ObservableSource<out T1>, ObservableSource<out T2>, ObservableSource<out T3>, Function3<T1, T2, T3, out R> ) combineLatest( ObservableSource<out T1>, ObservableSource<out T2>, ObservableSource<out T3>, ObservableSource<out T4>, Function4<T1, T2, T3, T4, out R> )
Como dije, Kotlin usa las Conversiones SAM para convertir una expresión de reference de function / lambda en una interfaz funcional de Java, pero no puede asignar una interfaz funcional de Java directamente.
El 4 ° parámetro del método combineLatest
en Kotlin, el comstackdor no puede inferir su tipo en absoluto, ya que el 4 ° tipo de parámetro puede ser io.reactivex.functions.Function3
u ObservableSource
. porque ObservableSource
es también una interfaz funcional de Java.
Cuando se encuentra con un conflicto de conversión de SAM como este, puede usar una function de adaptador que convierta un lambda a un tipo de SAM específico, por ejemplo:
typealias RxFunction3<T1, T2, T3, R> = io.reactivex.functions.Function3<T1,T2,T3,R> val f: RxFunction3<String, Boolean, Int, Double> = RxFunction3{ s, b, i-> 1.0}
Por lo tanto, debe usar una adaptación antes de usar lambda / Function Reference Expression , por ejemplo:
typealias RxFunction3<T1, T2, T3, R> = io.reactivex.functions.Function3<T1,T2,T3,R> fun <T1,T2,T3,R> KFunction3<T1,T2,T3,R>.toFunction3(): RxFunction3<T1, T2,T3,R> { return RxFunction3 { t1, t2, t3 -> invoke(t1, t2, t3) } }
Luego puede usar Expresión de reference de function como se muestra a continuación, por ejemplo:
Observable.combineLatest( strings(), booleans(), integers(), // v--- convert KFunction3 to RxFunction3 explicitly this::combine.toFunction3() )
- No se puede detectar el lanzamiento de exception después de que se cancela Kotlin coroutine
- ¿Cómo llamar a una function de nivel superior desde un método o una function de extensión de la misma firma?