2021. 9. 8. 22:00ㆍAndroid
쓸 때마다 헷갈리는 debounce, throttle...
이번 기회에 확실히 정리해 두고, 저와 같이 헷갈리시는 분들을 위해 공유합니다.
직접 테스트도 해보니 이해 쏙쏙
목차
debounce 함수
public final Observable<T> debounce(long timeout, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) {
Objects.requireNonNull(unit, "unit is null");
Objects.requireNonNull(scheduler, "scheduler is null");
return RxJavaPlugins.onAssembly(new ObservableDebounceTimed<>(this, timeout, unit, scheduler));
}
특정 시간(위에서 timeout 값)이 지난 후 제일 마지막으로 들어온 이벤트만 발생하도록 하는 함수. (말로 설명하기가 너무 어렵다!)
예시로 이해를 돕자.
특정 시간(timeout) 값이 5초라고 가정하고 위 그림을 설명해본다.
❤️이벤트가 들어오고, 그 이후 아무런 인풋이 없는 상태로 5초가 지났다. => ❤️이벤트 발생!
💛이벤트가 들어오고, 2초가 지날 때쯤 💚이벤트가 새로 들어왔다.
그럼 💚가 들어온 기준으로 5초 타이머가 새로 시작한다! 그 이후 아무런 인풋이 없는 상태로 5초가 지났다. => 💚이벤트 발생!
💙이벤트가 들어오고, 그 이후 아무런 인풋이 없는 상태로 5초가 지났다. => 💙이벤트 발생!
이제 이해가 조금 되는가!
debounce의 특징은, 타이머가 작동하고 있을 때, 새로운 이벤트가 들어오면 타이머는 리셋된다!
throttle 함수
public final Observable<T> throttleLast(long intervalDuration, @NonNull TimeUnit unit) {
return sample(intervalDuration, unit);
}
public final Observable<T> throttleLast(long intervalDuration, @NonNull TimeUnit unit, @NonNull Scheduler scheduler) {
return sample(intervalDuration, unit, scheduler);
}
RxJava에서 throttle 함수는 위와 같이 2종류가 있고, 개념은 굉장히 쉽다!
이벤트 발생이 일정 간격(intervalDuration)으로 일어난다. 그래서 위 함수를 보면 파라미터명이 intervalDuration(간격 시간)인 것!
throttleFirst
새로운 이벤트가 들어온 후, 일정한 시간 간격(intervalDuration) 이 지난 후에 해당 간격 중 가장 처음 들어온 이벤트를 발생시킨다.
예시로 이해를 돕자.
특정 시간(timeout)값이 5초라고 가정하고 위 그림을 설명해본다.
❤️이벤트가 들어오고 => ❤️이벤트 발생! 그 이후 아무런 인풋이 없는 상태로 5초가 지났다.
💛이벤트가 들어오고 => 💛이벤트 발생! 그 후 2초가 지날때쯤 💚이벤트가 새로 들어왔다. 그 이후 3초가 지났다. (throttleFirst 이기 때문에 이후에 들어온 초록이는 무시당함)
💠(하늘색하트가 없어서 요 아이로 대체..)이벤트가 들어오고 => 💠이벤트 발생! 그 후 3초가 지나고💙이벤트가 들어왔다. (파랑이 무시당함)
💜이벤트가 들어오고 => 💜이벤트 발생!
throttleLast
새로운 이벤트가 들어온 후, 일정한 시간 간격(intervalDuration) 이 지난 후에 해당 간격 중 가장 마지막으로 들어온 이벤트를 발생시킨다.
debounce vs throttle 비교 테스트
조건
아래와 같이 0초부터 시작해서 2초 간격으로 input 스트림에 값을 넣는다.
즉, for 문이 다 돌면 input 에는 아래의 값이 쌓여 있을 것이다.
=> [ "0초 후", "2초 후", "4초 후", ... , "20초 후" ]
val input = BehaviorSubject.create<String>()
for (i in 0..10) {
val text = "${i * 2}초 후"
input.onNext(text)
Thread.sleep(2000L)
}
그리고 debounce, throttle 에서의 타이머 또는 간격 시간은 5초로 설정.
debounce 결과
호호.. 결과 심플...
input.debounce(5000L, TimeUnit.MILLISECONDS, Schedulers.computation())
.subscribeOn(Schedulers.computation())
.subscribe {
println("LOG>> debounce result : $it")
}
20초 만 찍힌 이유는?!
위에서 설명했듯이, debounce 는 새로운 이벤트가 들어오면 타이머를 새로 리셋하는데,
이벤트가 들어오는 간격은 2초이고, debounce 타이머는 5초이니 이벤트가 들어올 때마다 타이머가 계속 리셋되는 것!! (아래 그림 참고)
위와 같은 결과가 나온 이유를 그림으로 풀이해봤다. 👇👇
throttleLast 결과
input.throttleLast(5000L, TimeUnit.MILLISECONDS, Schedulers.computation())
.subscribeOn(Schedulers.computation())
.subscribe {
println("LOG>> throttle result : $it")
}
위와 같은 결과가 나온 이유를 그림으로 풀이해봤다. 👇👇
throttleFirst 결과
input.throttleFirst(5000L, TimeUnit.MILLISECONDS, Schedulers.computation())
.subscribeOn(Schedulers.computation())
.subscribe {
println("LOG>> throttle result : $it")
}
간단 요약
- debounce, throttle 함수 모두 일정 시간 동안에 발생한 마지막 이벤트를 발생시키는 개념.
- debounce 의 경우, 새로운 이벤트가 들어올 때마다 타이머를 리셋시켜서, 이벤트가 들어온 후 특정 시간이 지났을 때 해당 이벤트를 발생시킴.
- throttle의 경우, 이벤트가 들어온 후 일정 시간 간격마다 이벤트가 발생한다. 일정 시간 간격 동안 가장 먼저 들어온 이벤트를 발생시키거나, 가장 마지막으로 들어온 이벤트를 발생시키거나
- TL;DR; 위에 있는 그림 설명들을 보자. 그림을 보면 깔끔하게 이해된다!
Reference
http://reactivex.io/documentation/operators/debounce.html
http://reactivex.io/documentation/operators/debounce.html#collapseRxSwift
https://proandroiddev.com/throttling-in-rxjava-2-d640ea5f7bf1
'Android' 카테고리의 다른 글
[Android] Room - Entity(table) 간의 관계(relationship) 정의하기 (1) | 2021.11.28 |
---|---|
[Android] EditText 실시간으로 특정 부분의 글자색 변경하기. (텍스트 하이라이트) (0) | 2021.10.04 |
[Android] Recyclerview 클릭한 아이템을 가운데로 scroll 되게 하기 (2) | 2021.08.16 |
[Android] Progress 를 나타내는 Custom ProgressBar 구현하기 (0) | 2021.08.08 |
[Android] Fragment에서 viewModel 접근을 onAttach() 이후에 해야하는 이유 (0) | 2021.07.17 |