-->

Polling using RXJava2 / RXAndroid 2 and Retrofit

2019-09-14 14:14发布

问题:

i would like to implement a Pollingservice which calls a REST Api every nDelay Seconds and notify all subscribers if the data has been changed. Now i have a little problem with my code since it always returns a value to my Consumer, even if the data has not been changed.

private Observable<List<HueLight>> pollingLightsObservable = null;

public Observable<List<HueLight>> getPollingLightsObservable() {
        if (pollingLightsObservable == null) {
            pollingLightsObservable = Observable.fromCallable(
                    () -> LightManager
                            .getInstance(context)
                            .getLights()
                            .blockingSingle())
                    //      .distinctUntilChanged( (l1, l1) -> !l1.equals(l2) )
                            .repeatWhen(o -> o.concatMap(v -> Observable.timer(1, TimeUnit.SECONDS)));

        }
        return pollingLightsObservable;
 }

Enabling or using the distinctUntilChanged dont change anything. Doesnt matter if i put it before or after my repeatWhen.

Since my RetroFit Call returns an Observable, i have to use blockingSingle(). Using the Observable directly it leads into a return of "4, 8, 12, 16, .." items with this sample:

LightManager.getInstance(context).getLights()
                            .repeatWhen(o -> o.concatMap(v -> Observable.timer(1, TimeUnit.SECONDS)))

Currently i subscribe from different classes/activites with

   this.lightChangeSubscriber = PollingManager
                .getInstance(getContext())
                .getPollingLightsObservable()
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(hueLights -> {
                    {
                        Log.d(TAG, "Lights received successfully! Size=" + hueLights.size());
                    }
                });

I would lovely avoid using interfaces and timer to create the polling. What would you recommend ?

回答1:

what about using some custom filter?

public class FilterDuplicateHueConfig implements Predicate<HueConfig> {

   private HueConfig lastVal;
   @Override 
   public boolean test(HueConfig newVal) {
      if(lastVal == null) {
         lastVal = newVal;
         return true;
      }
      ... compare here the two values and return true/false appropriately...
   }
}