Search code examples
androidretrofitretrofit2rx-javarx-java2

BackpressureStrategy.DROP not working as I expected


Let's suppose I have an activity showing the posts in RecyclerView and inside this activity, there is a refresh button.

When the user clicked on the refresh button I'll connect with the server to get posts again.

Let's suppose the user clicked on the refresh button and during trying to get the posts from the server, The user clicked on the refresh button again 16 times, That will cause connected with the server 17 times.

I tried to solve this problem by using BackpressureStrategy.DROP inside repeatWhen but BackpressureStrategy.DROP does not drop the connections during get the posts from the server.

PublishSubject<String> retrySubject = PublishSubject.create();
PublishSubject<String> repeatSubject = PublishSubject.create();

new Retrofit.Builder()
        .baseUrl("...")
        .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(API.class)
        .getPosts()
        .repeatWhen(objectFlowable -> objectFlowable.zipWith(repeatSubject.toFlowable(BackpressureStrategy.DROP), (o, s) -> s))
        .retryWhen(throwableFlowable -> throwableFlowable.zipWith(retrySubject.toFlowable(BackpressureStrategy.DROP), (throwable, s) -> s))
        .subscribe();

//repeatSubject.onNext("") inside refresh button
//retrySubject.onNext("") inside retry button

Solution

  • zipWith has a default prefetch amount of 128 and a minimum of 1 so there would be always one repeat to be triggered.

    If you want the subject only to be considered when the inner sequence is ready to repeat/retry, use flatMap:

    .repeatWhen(f -> 
        f.flatMap(e -> repeatSubject
                       .toFlowable(BackpressureStrategy.DROP)
                       .take(1)
        )
    )