Search code examples
androidrx-javaretrofit2

Rx and Retrofit: Changing ServiceApi request parameter in request loop started by repeatwhen or repeatuntill


I am using retrofit and RxJava for my application. I am executing a request which will hit the server every 1 sec. For this, I create retrofit service API with request params and subscribe on the returned observable and use repeatWhen.

Problem is , every time the request is hit, I want to change the request parameter sent with the request(Basically have to make it dynamic). How can I achieve this?

For eg Use case: sendLocation Api sending currrent location to server every 10 sec. How can this be achive this using retrofit and RxJava


Solution

  • @TassosBassoukos' answer works if you add the delay in. Specifically, here is a full example using github API that alternates calls between two users. Make sure not to let this run too long --

    public interface GitHubService {
        @GET("/users/{user}/repos")
        Observable<String> getRepo(@Path("user") String user);
    }
    
    static String[] users = {"octocat", "square"};
    static int i = 0;
    
    static String getUser() {
        return users[i++ % 2];
     }
    
    public void RxGitRepo() {
        OkHttpClient client = new OkHttpClient();
    
        Retrofit retrofit = new Retrofit.Builder()
          .client(client)
          .baseUrl("https://api.github.com")
          .addConverterFactory(ScalarsConverterFactory.create())
          .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
          .build();
    
       GitHubService gitHubService = retrofit.create(GitHubService.class);
       Observable
          .defer(() -> Observable.just(getUser()))
          .flatMap(user -> gitHubService.getRepo(user))
          .repeatWhen(done -> done.delay(2, TimeUnit.SECONDS))
          .subscribeOn(Schedulers.io())
          .subscribe(System.out::println);
    }
    

    For your use case, instead of polling the location every 10 seconds, you could set up your observable on the location and use that to trigger updates. Using a library like android-reactiveLocation, you can get an Observable that streams locations. Something along the lines of the following untested code --

    LocationRequest request = LocationRequest.create() 
                                 .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                                 .setInterval(10000);
    
    ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(context);
    Subscription subscription = locationProvider.getUpdatedLocation(request)
        .sample(10, TimeUnits.SECONDS)
        .flatMap(/* your retrofit call based on the observed location */)  
        .subscribe(/* subsciber for retrofit call results */);