1. Retarder l'action d'exécution
Il peut être implémenté à l'aide de la méthode TIMER + MAP. Le code est le suivant:
Observable.timer (5, timeunit.milliseconds) .map (valeur -> {return dosomething ();}). } 2. Retarder le résultat d'envoi
Ce scénario nécessite que l'action de génération de données soit exécutée immédiatement, mais le résultat est retardé dans l'envoi. Ceci est différent du scénario ci-dessus.
Ce scénario peut être mis en œuvre à l'aide Observable.zip .
L'opérateur ZIP combine les données transmises par plusieurs observables dans l'ordre, chaque données ne peut être combinée qu'une seule fois, et elles sont toutes commandées. Le nombre de données combinées finales est déterminée par l'observable, qui transmet le moins de données.
Pour les données au même emplacement de chaque observable, vous devez vous attendre. C'est-à-dire qu'après générer les données du premier emplacement du premier observable, vous devez attendre que les données du premier emplacement du deuxième observable soient générées, et après que les données au même emplacement de chaque observable soient générées, vous pouvez combiner selon les règles spécifiées. C'est vraiment ce que nous voulons utiliser.
Il existe de nombreux types de déclarations dans le ZIP, mais c'est à peu près la même, à savoir plusieurs observables, puis spécifier une règle pour traiter les données à l'emplacement correspondant de chaque observable et générer de nouvelles données. Voici l'un des plus simples:
Public Static <T1, T2, R> Observable <R> Zip (observable <? étend T1> O1, observable <? étend T2> O2, Func2 <? Super T1 ,? Super T2 ,? étend R> zipfonction);
Les résultats d'exécution de Push et Send à l'aide de ZIP sont les suivants:
Observable.zip (observable.timer (5, timeunit.millisecondes), observable.Just (doSomething ()), (x, y) -> y) .subscribe (System.out :: println));
3. Utilisez un repère pour effectuer certaines actions dans le thread spécifié
Comme dans le code suivant, bien que nous spécifions la méthode d'exécution du thread, la fonction doSomething() est toujours exécutée dans le thread appelé par le code actuel.
Observable.Just (DoSomething ()) .SubScribeon (Schedulers.io ()) .ObServeOn (Schedulers.Compputation ()) .Subscribe (V-> utils.printlnWithThread (v.toString ()););
Habituellement, nous utilisons les méthodes suivantes pour atteindre notre objectif:
Observable.Create (S -> {S.ENEXT (DoSomething ());}) .SubScribeon (Schedulers.io ()) .ObServeOn (Schedulers.Comptation ()) .Subscribe (v -> {utils.printlnwithThread (v.toString ());});Mais en fait, nous pouvons atteindre le même objectif en utilisant un repère.
À propos de différer
L'opérateur de report est le même que la création, juste, et d'autres opérateurs. Il crée des opérateurs de classe, mais toutes les données liées à cet opérateur ne prennent effet que si vous vous abonnez.
déclaration:
Public Static <T> Observable <T> Refer (Func0 <observable <T>> ObservableFactory);
L'observable dans FUNC0 du Defer n'est créé que lorsqu'il est abonné.
effet:
Ne créez pas l'observable jusqu'à ce qu'un observateur abonne; Créez un nouveau observable sur chaque abonnement.
En d'autres termes, l'observable est créé lors de l'abonnement.
Le problème ci-dessus est mis en œuvre avec différer:
Observable.defer (() -> observable.Just (DoSomething ())) .SubScribeon (schedulers.io ()) .observeon (schedulers.computation ()) .subscribe (v -> {utils.printlnWithThread (v.toString ());}); 4. Ne brise pas la structure de la chaîne à l'aide de compose
Nous voyons souvent le code suivant:
Observable.Just (DoSomething ()) .SubScribeon (Schedulers.io ()) .ObServeOn (Schedulers.Compputation ()) .Subscribe (v -> {utils.printlNWithThread (v.ToString ()); Dans le code ci-dessus, subscribeOn(xxx).observeOn(xxx) peut être le même à de nombreux endroits. Si nous prévoyons de le mettre en œuvre dans un certain endroit, nous pouvons l'écrire comme ceci:
Private Static <T> observable <T> ApplySchedulers (observable <T> observable) {return observable.subscribeon (schedulers.io ()) .observeon (scheners.computation ()); }Mais chaque fois que nous devons appeler la méthode ci-dessus, ce sera à peu près comme ce qui suit, et le plus à l'extérieur est une fonction, ce qui équivaut à briser la structure de liaison:
ApplySchedulers (observable.from (SomeSource) .map (new func1 <data, data> () {@Override Public Data Call (Data Data) {return manipuler (data);}})) .Subscribe (new Action1 <sat> () {@Override public Void Call (données données) {Dosomething (Data);}});L'opérateur de composition peut être utilisé pour atteindre le but de ne pas briser la structure de liaison.
L'énoncé de compose est le suivant:
Composé observable public (transformateur <? Super T ,? étend R> transformateur);
Son paramètre entrant est une interface de transformateur et la sortie est observable. Le transformateur est en fait un Func1<Observable<T> , Observable<R>> , en d'autres termes: un type d'observable peut être converti en un autre type d'observable.
Autrement dit, Compose peut convertir l'observable d'origine en un autre observable via la méthode de conversion spécifiée (transformateur de paramètre d'entrée).
Via Compose, utilisez la méthode suivante pour spécifier la méthode du thread:
Transformateur statique privé <T> <T, T> ApplySchedulers () {return nouveau transformateur <t, t> () {@Override public Observable <T> Call (observable <t> observable) {return observable.subscribeon (schedulers.io ()) .obServeon (Schedulers.Compation ()); }}; } Observable.Just (DoSomething ()). Compose (applatSchedulers ()) .Subscribe (v -> {utils.printlnWithThread (v.toString ());});La fonction applique auxChadulers peut être encore simplifiée en utilisant des expressions de lambda à ce qui suit:
Transformateur statique privé <T> <T, T> ApplySchedulers () {return observable-> observable.subscribeon (schedulers.io ()) .obServeOn (schedulers.computation ()); } 5. Utilisez des résultats d'exécution différents en fonction de la priorité
Le titre ci-dessus n'a probablement pas exprimé le scénario que je voulais exprimer clairement. En fait, le scénario que je souhaite exprimer est similaire au scénario habituel d'obtenir des données de réseau: s'il y a un cache, il sera obtenu à partir du cache, et s'il y en a non, il sera obtenu à partir du réseau.
Il est nécessaire ici que s'il y a un cache, l'action d'obtenir des données du réseau ne sera pas effectuée.
Cela peut être implémenté en utilisant d'abord CONCAT +.
Concat fusionne plusieurs observables en un observable et renvoie le final observable. Et ces données sont comme être envoyées par un observable. Les paramètres peuvent être plusieurs observables ou itérator contenant observralbe.
Les données dans le nouveau observable sont organisées dans l'ordre de l'observable dans le Concat d'origine, c'est-à-dire que les données du nouveau résultat sont triées dans l'ordre d'origine.
Voici la mise en œuvre des exigences ci-dessus:
Observable.concat (getDataFromCache (), getDataFromNetwork ()). First () .Subscribe (v-> System.out.println ("Result:" + V)); // obtenir des données de Cache privé statique observable <string> getDataFromCache () {return observable.create (s -> {// dosomething pour obtenir des données int value = new random (). NextInt (); valeur = valeur% 2; if (valeur! = 0) {s.onnext ("data from cache:" + value); // créer des données} //s.onerror. S.OnCompleted ();}); } // Obtenez des données du réseau privé static observable <string> getDataFromNetwork () {return observable.create (s -> {for (int i = 0; i <10; i ++) {utils.println ("obs2 générate" + i); s.onnext ("data from:" + i); // generate data} s.onCOMPleted ();}); }Dans l'implémentation ci-dessus, si GetDataFromCache a des données, le code ici dans GetDataFromnetwork ne sera pas exécuté, ce qui est exactement ce que nous voulons.
Il y a plusieurs implémentations ci-dessus qui nécessitent une attention:
1. Il est possible que les données ne puissent pas être obtenues à partir des deux endroits. Dans ce scénario, l'utilisation d'abord lancera une exception NosuchementElementException. Si ce scénario est le cas, vous devez remplacer le premier ci-dessus par FirstOrdefault.
2. Dans getDataFromCache() ci-dessus, s'il n'y a pas de données, nous appelons directement sur complété. Si nous n'appelons pas oncompleted mais appelons onError, l'utilisation de Concat susmentionnée n'obtiendra aucun résultat. Parce que lorsque Concat reçoit une erreur, la fusion s'arrête. Par conséquent, si vous souhaitez utiliser ONERROR, vous devez utiliser ConcatdelayError au lieu de concat.concatDelayError ConcatdelayError ignorera d'abord l'erreur et reportera l'erreur jusqu'au traitement final.
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article sera d'une aide à votre étude ou à votre travail. Si vous avez des questions, vous pouvez laisser un message pour communiquer.