Amit
Amit

Reputation: 225

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

Upvotes: 3

Views: 1676

Answers (3)

Alexander Perfilyev
Alexander Perfilyev

Reputation: 6839

How about this?

    AtomicInteger requestParam = new AtomicInteger();

    apiCall.request(requestParam)
            .doOnNext(response -> requestParam.set(response.getRequestParam()))
            .repeatWhen(objectObservable -> objectObservable
                    .delay(1, TimeUnit.SECONDS)
                    .flatMap(o -> Observable.just(requestParam.get())
                    .takeWhile(integer -> /* condition */ )));

Upvotes: 2

iagreen
iagreen

Reputation: 31996

@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 */);

Upvotes: 5

Tassos Bassoukos
Tassos Bassoukos

Reputation: 16142

Use something like this:

Observable
.defer(() -> Observable.just(getLocation))
.flatMap(location -> doNetworkCall(location))
.repeatWhen(...)

Upvotes: 1

Related Questions