최근 진행하고 있는 사이드 프로젝트에서 이메일 회원가입, 이메일 변경등의 동작에서 버튼 클릭을 하면 인증번호가 보내지고 올라온 바텀시트에 인증번호를 입력하는 플로우를 진행하고 있었다. 하지만 중복 클릭에 대한 어떠한 처리도 해두지 않았기에 여러번 누르게 되면 api 호출이 여러번 되는 문제가 생겼고 확장함수를 만들어서 Modifier에서 사용하는 방식으로 해결을 했다.
우선 내가 해결한 코드는 아래와 같다.
fun Modifier.throttleClick(
throttleTime: Long = 1000L,
onClick: () -> Unit
): Modifier {
var lastClickTime = 0L
return this.clickable {
val currentTime = System.currentTimeMillis()
if (currentTime - lastClickTime >= throttleTime) {
onClick()
lastClickTime = currentTime
}
}
}
// 중복 클릭을 제한하는 시간을 설정하고
// 그 시간 내에 요청이 다시 들어온다면 무시하고
// 그 시간이 넘어서 요청이 오면 정상적인 요청이라고 판단.
위는 확장 함수 형태로 따로 분리를 한것이고, 사용은 아래와 같이 하면 됩니다.
Text(
text = "인증 번호 보내기",
modifier = Modifier
.fillMaxWidth()
.height(61.dp)
.clip(RoundedCornerShape(20))
.background(Color.Blue)
.throttleClick {
// 클릭 시 동작
}
.padding(vertical = 16.dp),
color = Color.White,
textAlign = TextAlign.Center
)
찾아보니 내가 해결한 방법은 Throttle이라는 방식이다. 많이 사용하는 방식에는 Debounce와 Throttle가 있는데 간단히 설명해보자면 아래와 같다.
Debounce : 발생하는 이벤트를 그룹화하여, 일정 시간동안 이벤트를 발생하지 않으면 마지막 이벤트를 전달하는 기법. delay를 정하고 이벤트가 발생하다가 잠시 멈추는 시점에 delay만큼의 시간이 지나게 되면 그전에 받은 마지막 이벤트를 전달하는 식입니다.
Debounce는 언제 사용할까??
대표적인 예시로는 검색어를 입력했을 때 검색어에 따라서 추천 검색어 미리보기가 바뀌는 형태로 많이 사용합니다.
Throttle : 일정 주기마다 이벤트를 캐치해서 전달하는 기법. Debounce는 마지막 이벤트를 기준으로 delay만큼 Timer를 돌리지만, Throttle은 이벤트와 관계 없이 Timer를 돌린 상태에서 발생하는 이벤트를 감지합니다.
Throttle의 대표적인 예시로는 버튼 중복 클릭 방지가 있습니다.
참고
- https://labs.brandi.co.kr/2021/05/13/leesy5.html
'안드로이드' 카테고리의 다른 글
[Compose] LaunchedEffect Unit, true (0) | 2024.10.05 |
---|---|
[Compose] viewModel(), hiltViewModel() 차이는 뭘까?? (1) | 2024.10.04 |
[Android] ViewModel에서의 context (0) | 2024.09.21 |
[Compose] Navigation back stack (0) | 2024.09.18 |
상태 스냅샷 시스템(State Snapshot System) (0) | 2024.07.04 |