Actualización de datos mediante SQLBrite + Retrofit

Aquí está mi caso de uso:

Estoy desarrollando una aplicación que se comunica con un servidor a través de una API REST y almacena los datos recibidos en una base de datos SQLite (se utiliza como un caché de algunos tipos).

Cuando el usuario abre una pantalla, debe ocurrir lo siguiente:

  1. Los datos se cargan desde el DB, si están disponibles.
  2. La aplicación llama a la API para actualizar los datos.
  3. El resultado de la llamada API se mantiene en la base de datos.
  4. Los datos se vuelven a cargar desde el DB cuando se intercepta la notificación de cambio de datos.

Esto es muy similar al caso presentado aquí , pero hay una ligera diferencia.

Puesto que estoy usando SQLBrite, los observables de la base de datos no terminan (porque hay un ContentObserver registrado allí, que empuja nuevos datos abajo de la corriente), así que los métodos como el concat , la merge , el etc. no trabajarán.

Actualmente, he resuelto esto utilizando el siguiente enfoque:

 Observable.create(subscriber -> { dbObservable.subscribe(subscriber); apiObservable .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) .subscribe( (data) -> { try { persistData(data); } catch (Throwable t) { Exceptions.throwOrReport(t, subscriber); } }, (throwable) -> { Exceptions.throwOrReport(throwable, subscriber); }) }) 

Parece que funciona bien, pero no parece elegante y "correcto".

¿Puede sugerirme o indicarme un recurso que explique cuál es la mejor manera de manejar esta situación?

La solución a su problema es en realidad muy fácil y limpio si cambia la forma de pensar un poco. Estoy utilizando la misma interacción de datos (Retrofit + Sqlbrite) y esta solución funciona perfectamente.

Lo que tienes que hacer es usar dos suscripciones observables separadas, que se ocupan de procesos completamente diferentes.

  1. Database -> View : Este se utiliza para adjuntar su View ( Activity , Fragment o lo que sea muestra sus datos) a los datos persistentes en db. Usted se suscribe a él UNA VEZ para la View creada.
 dbObservable .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(data -> { displayData(data); }, throwable -> { handleError(throwable); }); 
  1. API -> Database : El otro para buscar los datos de api y persistir en el db. Usted se suscribe a ella cada vez que desee actualizar sus datos en la base de datos.
 apiObservable .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) .subscribe(data -> { storeDataInDatabase(data); }, throwable -> { handleError(throwable); }); 

EDITAR:

Usted no quiere "transformar" ambos observables en uno, puramente por la razón que ha incluido en su pregunta. Ambos observables actúan de manera completamente diferente.

El observable de Retrofit actúa como un Single . Hace lo que necesita hacer, y termina (con onCompleted ).

El observable de Sqlbrite es un Observable típico, él emitirá algo cada vez que una tabla específica cambia. Teóricamente debería terminar en el futuro.

Ofc usted puede trabajar alrededor de esa diferencia, pero le llevaría lejos, lejos de tener un código limpio y fácilmente legible.

Si realmente, realmente necesita exponer una sola observable , sólo puede ocultar el hecho de que está realmente suscribirse a la observable de retrofit al suscribirse a su base de datos.

  1. Envuelva la suscripción de Api en un método:
 public void fetchRemoteData() { apiObservable .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) .subscribe(data -> { persistData(data); }, throwable -> { handleError(throwable); }); } 
  1. fetchRemoteData en la suscripción
 dbObservable .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnSubscribe(() -> fetchRemoteData()) .subscribe(data -> { displayData(data); }, throwable -> { handleError(throwable); }); 

Te sugiero que realmente pienses en todo eso. Porque el hecho de que te estás forzando a la posición en la que necesitas un solo observable, podría estar restringiéndote bastante. Creo que esta será la cosa exacta que te obligará a cambiar tu concepto en el futuro, en lugar de protegerte del cambio mismo.

  • convertir a lambda de rx java expresión
  • Evento de RxJava de incendio sólo cambia cuando Fragmento es visible en ViewPager
  • Realm, RxJava, asObservable () y doOnUnsubscribe ()
  • ¿Cómo obtener el último valor de BehaviorSubject?
  • ¿Cómo utilizar Flowable en RxJava 2?
  • Manejador de errores por defecto de RxJava
  • RxJava + Retrofit + sondeo
  • Cómo hacer que flatMap se ejecute en un subproceso de fondo
  • RxJava y eventos esporádicos al azar en Android
  • IllegalArgumentException: No se pudo localizar el adaptador de llamada para rx.Observable RxJava, Retrofit2
  • RxJava dividir uno Observable a dos subObservables
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.