Android

FlowBinding 사용하여 코드 간소화

그란. 2023. 1. 11. 14:53

flowbinding 이란?

View의 이벤트 연결을 Flow<Unit>, Flow<T> 로 변형해주는 라이브러리


사용 이유? 

코드 간소화 및 중복클릭방지 처리, flow의 장점 이용 가능

 

소셜 로그인시 각 버튼마다 이벤트를 연결해야 하는 경우

아래와 같은 코드를

apple.setOnClickListener { 
    viewModel.login(AuthType.APPLE)    
}

google.setOnClickListener {
    viewModel.login(AuthType.GOOGLE)
}

kakao.setOnClickListener {
    viewModel.login(AuthType.KAKAO)
}

naver.setOnClickListener {
    viewModel.login(AuthType.NAVER)
}

facebook.setOnClickListener {
    viewModel.login(AuthType.FACEBOOK)
}

 

이렇게 변형할 수 있다.

merge(
    apple.throttleClick().map { AuthType.APPLE },
    google.throttleClick().map { AuthType.GOOGLE },
    kakao.throttleClick().map { AuthType.KAKAO },
    naver.throttleClick().map { AuthType.NAVER },
    facebook.throttleClick().map { AuthType.FACEBOOK },
).bind {
    viewModel.login(it)
}

기본 사용법 

라이브러리 추가 : "io.github.reactivecircus.flowbinding:flowbinding-android:1.2.0" 

view.clicks()
    .onEach {
       // handle view clicked
    }.launchIn(uiScope)
textView.textChanges()
    .onEach { text ->
         // handle text
    }.launchIn(uiScope)

이외에도 checkedChanges()등 해당 뷰에서 주로 사용하는 이벤트들이 정의되어 있다.

 


활용법 

  • 중복 클릭 방지 처리 
fun <T> Flow<T>.throttleFirst(): Flow<T> = flow {
    var lastEmissionTime = 0L
    collect { upstream ->
        val currentTime = System.currentTimeMillis()
        if (currentTime - lastEmissionTime > 700L) {
            lastEmissionTime = currentTime
            emit(upstream)
        }
    }
}


fun View.throttleClick(): Flow<Unit> = this.clicks()
    .throttleFirst()

 

 

  • scope 지정 및 확장함수 변형
abstract class BaseActivity() {

  fun <T> Flow<T>.bind(block: (T) -> Unit) 
    	= onEach { block(it) }.launchIn(lifecycleScope)
}


View.throttleClick()
    .bind{
      //Handle Event
    }

 

 

BaseFragment 에서는 아래의 라싸스코프 사용

viewLifecycleOwner.lifecycleScope

 

깔끔하게 사용할 준비 완료