Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android limit specific API call to one in 3 seconds

I want to limit /test API call to be called once in 3 seconds, so for instance:

2021-09-21 14:09:19.920 V/OkHttp: --> GET https://xxx/test
2021-09-21 14:09:20.031 V/OkHttp: <-- 200 https://xxx/test (109ms)
2021-09-21 14:09:20.038 V/OkHttp: --> GET https://xxx/test
2021-09-21 14:09:20.136 V/OkHttp: <-- 200 https://xxx/test (96ms)
2021-09-21 14:09:20.146 V/OkHttp: --> GET https://xxx/test
2021-09-21 14:09:20.315 V/OkHttp: <-- 200 https://xxx/test (168ms)
2021-09-21 14:09:20.325 V/OkHttp: --> GET https://xxx/test
2021-09-21 14:09:20.499 V/OkHttp: <-- 200 https://xxx/test (172ms)
2021-09-21 14:09:20.514 V/OkHttp: --> GET https://xxx/test
2021-09-21 14:09:20.615 V/OkHttp: <-- 200 https://xxx/test (100ms)
2021-09-21 14:09:20.628 V/OkHttp: --> GET https://xxx/test
2021-09-21 14:09:20.721 V/OkHttp: <-- 200 https://xxx/test (91ms)
2021-09-21 14:09:20.734 V/OkHttp: --> GET https://xxx/test
2021-09-21 14:09:20.827 V/OkHttp: <-- 200 https://xxx/test (87ms)

Would be called once:

2021-09-21 14:09:19.920 V/OkHttp: --> GET https://xxx/test
2021-09-21 14:09:20.031 V/OkHttp: <-- 200 https://xxx/test (109ms)

For test purpose, I'm doing:

repeat(10) { index ->
    apiRepo.test() //Returns Single
        .toObservable()
        .debounce(3, TimeUnit.SECONDS)
        .subscribe({}, { Timber.e(it) })
    }

I come from Coroutine world, so I think I've misunderstood how debounce works, because I still get 10 calls (within 2 seconds), while I expect 1 in 3 seconds.

like image 372
MaaAn13 Avatar asked Sep 21 '21 11:09

MaaAn13


Video Answer


2 Answers

You create a new debounce ten times. That is why it is not working as expected. To achieve what you want you can use PublishSubject.

val apiCallSubject = PublishSubject.create<Unit>()

apiCallSubject
    .debounce(3, TimeUnit.SECONDS)
    .flatMapSingle { apiRepo.test() }
    .subscribe({}, { Timber.e(it) })

repeat(10) { apiCallSubject.onNext(Unit) }

The point is that Observable which you debounce has to emit multiple items. In your case it is emitting only one but ten times.

like image 111
lukjar Avatar answered Oct 21 '22 16:10

lukjar


You create new observable each iteration. Your apiRepo is returning new Observable each time. You need to do something like this:

val publisher = PublishSubject.create<Unit>()
Observable.fromPublisher(publisher).debounce(3, TimeUnit.SECONDS).flatMap { api.testApi() }.subscribe({}, { Timber.e(it) })

repeat(1000000){
   publisher.onNext(Unit)
}

From the loop you are emiting new items and as soon onNext() is called, the chain will react upon it.

like image 42
Nikola Despotoski Avatar answered Oct 21 '22 16:10

Nikola Despotoski