J'enchaîne des opérations asynchrones en utilisant RxJava, et j'aimerais passer une variable en aval:
Observable
.from(modifications)
.flatmap( (data1) -> { return op1(data1); })
...
.flatmap( (data2) -> {
// How to access data1 here ?
return op2(data2);
})
Cela semble être une tendance commune mais je n’ai pas pu trouver d’information à ce sujet.
Le conseil que j'ai reçu du forum Couchbase est d'utiliser des observables imbriquées:
Observable
.from(modifications)
.flatmap( (data1) -> {
return op1(data1)
...
.flatmap( (data2) -> {
// I can access data1 here
return op2(data2);
})
});
EDIT: Je vais marquer ceci comme la réponse acceptée car cela semble être la plus recommandée. Si votre traitement est trop complexe pour tout imbriquer, vous pouvez également vérifier la solution avec des appels de fonction.
Une autre possibilité consiste à mapper le résultat de op1
à un org.Apache.commons.lang3.Tuple.Pair
contenant la variable et à le transmettre:
Observable
.from(modifications)
.flatmap( (data1) -> {
return op1(data1).map( obj -> { return Pair.of(data1,obj); });
})
...
.flatmap( (dataPair) -> {
// data1 is dataPair.getLeft()
return op2(dataPair.getRight());
})
Cela fonctionne mais il est un peu inconfortable d’avoir des variables cachées dans Pair/Triple/... et cela devient très verbeux si vous utilisez la notation Java 6.
Je me demande s’il existe une meilleure solution. Peut-être qu'un opérateur de RxJava pourrait vous aider?
Une possibilité serait d'utiliser un appel de fonction:
private static Observable<T> myFunc(final Object data1) {
return op1(data1)
...
.flatmap( (data2) -> {
// I can access data1 here
return op2(data2);
});
}
Observable
.from(modifications)
.flatmap( (data1) -> { return myFunc(data1); })
MAIS: corrigez-moi si je me trompe, mais cela ne ressemble pas à la méthode de programmation réactive
flatmap peut prendre un deuxième argument:
Observable.just("foo")
.flatMap(foo -> Observable.range(1, 5), Pair::of)
.subscribe(pair -> System.out.println("Result: " + pair.getFirst() + " Foo: " + pair.getSecond()));
Vous pouvez utiliser la variable "globale" pour y parvenir:
Object[] data1Wrapper = new Object[]{null};
Object[] data2Wrapper = new Object[]{null};
Observable
.from(modifications)
.flatmap(data1 -> {
data1Wrapper[0] = data1;
return op1(data1)
})
...
.flatmap(data2 -> {
// I can access data1 here use data1Wrapper[0]
Object data1 = data1Wrapper[0];
data2Wrapper[0] = data2;
return op2(data2);
})
la solution sur ce fil fonctionne, mais pour les chaînes complexes cela rend le code difficile à lire, je devais passer plusieurs valeurs et ce que je fis fut de créer une classe privée avec tous les paramètres.
private class CommonData{
private string data1;
private string data2;
*getters and setters*
}
...
final CommonData data = new CommonData();
Observable
.from(modifications)
.flatmap( (data1) -> {
data.setData1(data1);
return op1(data1);
})
...
.flatmap( (data2) -> {
data2 = data.getData1() + "data 2... ";
data.setData2(data2);
return op2(data2);
})
j'espère que ça aide
Je sais que c’est une vieille question, mais en utilisant RxJava2 & lambda, vous pouvez utiliser quelque chose comme:
Observable
.from(modifications)
.flatMap((Function<Data1, ObservableSource<Data2>>) data1 -> {
//Get data 2 obeservable
return Observable.just(new Data2())
}
}, Pair::of)
Au prochain flux (flatmap/map), votre paire de résultats sera (data1, data2)