OnNext comience otro Observable

¿Hay alguna manera más limpia de hacer lo siguiente?

Tengo un observable de Android que debuta las peticiones. OnNext llama a una segunda observable.

{// when creating the android activity searchTextEmitterSubject = PublishSubject.create(); subscription = AndroidObservable.bindActivity(this, Observable.switchOnNext(searchTextEmitterSubject)) .debounce(100, TimeUnit.MILLISECONDS, Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<String>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { Log.d("a",s); pa.doSearch(s); } }); } @OnTextChanged(R.id.ed) public void onTextEntered(CharSequence charsEntered) { searchTextEmitterSubject.onNext(getASearchObservableFor(charsEntered.toString())); } private Observable<String> getASearchObservableFor(final String searchText) { return Observable.create( (Subscriber<? super String> subscriber) -> subscriber.onNext(searchText)).subscribeOn(Schedulers.io()); } 

DoSearch instancia una segunda observable:

 public void doSearch(String string) { AlbumEndpoint albumEndpoint = API.getRestAdapter().create(AlbumEndpoint.class); Observable<Point> observable = albumEndpoint.searchPoint(string); mAdapterDataSubscription = AndroidObservable.bindActivity((Activity) getContext(), observable) .subscribe(mAdapterDataObserver); } private Observer<Point> mAdapterDataObserver = new Observer<Point>() { @Override public void onCompleted() { mAdapterDataSubscription.unsubscribe(); } @Override public void onError(Throwable e) { e.printStackTrace(); } @Override public void onNext(Point point) { List<Point.Result> results = point.getResults(); mData.addAll(results); notifyDataSetChanged(); } }; 

Funciona. ¿Pero hay una manera de "combinar" las dos corrientes en uno mejorando la legibilidad o para crear un código óptimo?


Editar : Por razones de integridad y cualquier persona interesada en el futuro me las arreglo para encoger el código en:

 Observable<EditText> searchTextObservable = ViewObservable.text(ed); searchTextObservable.debounce(100, TimeUnit.MILLISECONDS) .flatMap(editText -> { String string = editText.getText().toString(); AlbumEndpoint albumEndpoint = getRestAdapter().create(AlbumEndpoint.class); return albumEndpoint.searchPoint(string); }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(mAdapterDataObserver); 

Un par de cosas:

No estoy seguro, ¿por qué está envolviendo los eventos de cambio de texto en un nuevo Observable cada vez en lugar de simplemente entregarlos a su tema de inmediato:

Por lo tanto, en lugar de:

 @OnTextChanged(R.id.ed) public void onTextEntered(CharSequence charsEntered) { searchTextEmitterSubject.onNext(getASearchObservableFor(charsEntered.toString())); } 

prueba esto:

 @OnTextChanged(R.id.ed) public void onTextEntered(CharSequence charsEntered) { searchTextSubject.onNext(charsEntered.toString()); } 

Por supuesto, entonces tendría un PublishSubject<String> lugar de PublishSubject<Observable<String>> .

Pero usted podría saltar el onNextSwitch y apenas debounce su asunto y continuar de allí.

Para simplificar aún más las cosas, sólo puede utilizar ViewObservables desde el paquete rxjava Android. No los he usado últimamente, pero debería funcionar así:

 Observable<OnTextChangeEvent> searchTextObservable = ViewObservable.text(tvSearch); 

A OnTextChangeEvent se emitirá cada vez que se llama a AfterTextChanged de afterTextChanged subyacente (en ButterKnife, por defecto, se utiliza onTextChanged , por lo que puede ser una diferencia sutil).

En caso de que me faltó alguna razón importante para envolver cada cambio de texto en un Observable, esto también se puede lograr de una manera más sencilla:

 @OnTextChanged(R.id.ed) public void onTextEntered(CharSequence charsEntered) { searchTextEmitterSubject.onNext( Observable.just(charsEntered.toString()) ); } 

Tenga en cuenta que también omitió el subscribeOn(Schedulers.io()) – Nunca he sentido la necesidad de mover a los oyentes de eventos desde el hilo de interfaz de usuario a algún otro hilo. ¿Me estoy perdiendo de algo?

Finalmente, podrías usar flatMap para ejecutar la búsqueda de cada término de búsqueda (estoy usando mi propio Observable<OnTextChangeEvent> aquí):

 searchTextObservable .debounce(100, TimeUnit.MILLISECONDS) .flatMap(new Func1<OnTextChangeEvent, Observable<Point>>() { @Override public Observable<Point> call(OnTextChangeEvent event) { final String string = event.text.toString(); AlbumEndpoint albumEndpoint = API.getRestAdapter().create(AlbumEndpoint.class); Observable<Point> pointObservable = albumEndpoint.searchPoint(string); return AndroidObservable.bindActivity((Activity) getContext(), pointObservable); } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(mAdapterDataObserver); 

Puede que necesite mover su pointObservable al subproceso de IO si el punto de entrada de álbum no lo hace ya.

¡Espero que esto ayude!

EDIT: Lo siento, me olvidé de explicar lo que es OnTextChangeEvent . Eso es una parte de rx-android – puede echar un vistazo al código fuente aquí:

https://github.com/ReactiveX/RxAndroid/blob/0.x/src/main/java/rx/android/events/OnTextChangeEvent.java

Es sólo un POJO simple que contiene una referencia al EditText que fue cambiado, así como el contenido actual del EditText. Este último es lo que estaba usando en el flatMap .

  • Utilice RxJava y Retrofit para iterar a través de la lista y aumentar los resultados basados ​​en subconsultas
  • ¿Cómo ejecutar 2 consultas secuencialmente en un Android RxJava Observable?
  • Creando Observable sin utilizar Observable.create
  • RxJava2 función de rebote no funciona correctamente en RecyclerView - Android
  • RxJava reintentoCuando vuelve a suscribir la propagación
  • ¿Dónde se puede encontrar AndroidObservable.fromBroadcast ahora?
  • Encadenamiento de llamadas de Retrofit con RxJava y devolución del objeto principal
  • Prueba de unidad de Android con Retrofit / RxJava / Roboletric y Mockito
  • RXJava - Dividir y combinar un Observable
  • Obtenga el código de estado de la respuesta utilizando Retrofit 2.0 y RxJava
  • No encontró la clase rx.android.schedulers.AndroidSchedulers
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.