2015-10-27 1 views
3

App utilise RxJava pour effectuer un appel réseau, puis modifier les résultats avec les données de la base de données et les afficher. L'application écoute les modifications de la base de données avec android.database.ContentObserver et modifie les données en cas de modification. Actuellement, il fonctionne avec le code ci-dessous, mais y at-il une façon plus agréable RX comment y parvenir? Merci!rxjava et android.database.contentobserver

Observable<ArrayList<Foo>> observable = Observable.create(new Observable.OnSubscribe<ArrayList<Foo>>() { 

      @Override 
      public void call(Subscriber<? super ArrayList<Foo>> subscriber) { 
       //make api call and get list of foos 
       ArrayList<Foo> apiResults = api.getFooList(); 
       //loop results and if foo is already in local sqlite db, update it with local values 
       for (Foo foo : apiResults) { 
        if(localSqlite.contains(foo){ 
         foo.update(localSqlite.get(foo)); 
        } 
       } 

       subscriber.onNext(apiResults); 

       HandlerThread observerThread = new HandlerThread("ContentObserver-thread"); 
       observerThread.start(); 
       final ContentObserver co = new ContentObserver(new Handler(observerThread.getLooper())) { 
         @Override 
         public void onChange(boolean selfChange) { 
          super.onChange(selfChange); 

          for (Foo foo : apiResults) { 
           if(localSqlite.contains(foo){ 
           foo.update(localSqlite.get(foo)); 
          } 

          subscriber.onNext(apiResults); 
       } 

        mContext.getContentResolver().registerContentObserver(uri, true, co); 

        subscriber.add(Subscriptions.create(new Action0() { 
         @Override 
         public void call() { 
       mContext.getContentResolver().unregisterContentObserver(co); 
         } 
        })); 

      } 


Subscription subscription = observable 
        .subscribeOn(Schedulers.io()) 
        .observeOn(AndroidSchedulers.mainThread()) 
        .subscribe(subscriber); 
+0

Avez-vous trouvé quelque chose? – Dima

+0

@Dima Non, j'utilise le code ci-dessus – vandzi

+0

@vandzi Peut-être que vous pouvez jeter un oeil à SQLbrite https://github.com/square/sqlbrite ou celui-ci https://github.com/yahoo/squidb/wiki/Observing- avec-RxJava – box

Répondre

0

boîte de suggestion d'enquêter sur SqlBrite est probablement le meilleur plan d'action, mais si vous n'avez pas le temps d'apprendre une nouvelle API est une technique fraîche ici que j'ai trouvé.

Si vous enroulez chaque résultat de requête de base de données dans un objet de comportement, vous pouvez le mettre en cache dans un hashmap en utilisant son URI comme clé. Ensuite, lorsque vous substituez la méthode de l'observateur contenu onChange, vous pouvez facilement pousser un aval objet rafraîchi:

final protected MaxSizeHashMap<Uri, Subject<T, T>> subjectMap = new MaxSizeHashMap<>(cacheSize/300); 

final private ContentObserver contentObserver = new ContentObserver(new Handler()) { 
     @Override 
     public void onChange(boolean selfChange, Uri uri) { 
      super.onChange(selfChange, uri); 

      if (subjectMap.containsKey(uri)) { 
       subjectMap.get(uri).onNext(query(uri)); 
      } 
     } 
    }; 

ensuite dans votre méthode get, construire l'objet, l'envelopper dans un sujet du comportement et l'ajouter à la carte avant de retourner l'observable:

public Observable<T> getFoo(U id) { 
    Uri uri = getUriForId(id); 

    if (!subjectMap.containsKey(uri)) { 
     subjectMap.put(uri, BehaviorSubject.create(query(id))); 
    } 

    return subjectMap.get(uri); 
}