-
안드로이드 비동기 처리 2-4 (실시간 검색 with EditText)안드로이드 학습/Android 기술면접 대비 코드 2024. 11. 1. 11:03
이전 내용까지 Rxjava가 무엇인지와 기초적으로 사용하는 것을 알아봤다.
과연 실제로는 어떻게 활용될지가 궁금했다. 그래서 찾아보니 아래와 같은 상황에 사용 가능하다.
- UI 이벤트 처리 (실시간 검색, 버튼 클릭)
- 네트워크 통신
- 데이터베이스
- 그 외에 비동기 방식들
RxBinding 라이브러리를 사용하면 Button 클릭이나 EditText 텍스트 변경과 같은 UI 이벤트를 Observable로 만들어 이벤트 기반의 데이터 흐름을 처리할 수 있다.
그래서 이번에는 RxBinding을 활용해서 실시간 검색하는 방법을 먼저 학습하려 한다.
실시간 검색은 EditText의 텍스트 변화를 구독하여 실시간 text 변화를 인식해서 검색 기능을 구현할 수 있다.
1. build.gradle
implementation("io.reactivex.rxjava3:rxandroid:3.0.2") implementation("io.reactivex.rxjava3:rxjava:3.1.5") implementation("io.reactivex.rxjava3:rxkotlin:3.0.0") implementation("com.jakewharton.rxbinding4:rxbinding:4.0.0")
java로 rxJava를 사용한다면
implementation("io.reactivex.rxjava3:rxjava:3.1.5")
kotlin으로 rxJava를 사용한다면
implementation("io.reactivex.rxjava3:rxkotlin:3.0.0")
2. Fragment
Activity에 만드는 것이나 Fragment를 만드는 것이나 별 차이가 없다. 나의 프로젝트가 Fragment로 구성되어 있어 Fragment에 추가했다.
class RxAndEtFragment : ViewBindingBaseFragment<FragmentRxAndEtBinding>() { private lateinit var rxJavaViewModel: RxJavaBasicViewModel private lateinit var disposeable: Disposable override fun getViewBinding(): FragmentRxAndEtBinding { return FragmentRxAndEtBinding.inflate(layoutInflater) } override fun initContentInOnViewCreated() { rxJavaViewModel = ViewModelProvider(this)[RxJavaBasicViewModel::class.java] val editTextChangeObservable = binding.etRxEdit.textChanges() val observer = object : Observer<String> { override fun onSubscribe(d: Disposable) { disposeable = d } override fun onNext(t: String) { binding.tvRxEditResult.text = t // EditText 내용에 따른 TextView 변경 } override fun onError(e: Throwable) {} override fun onComplete() {} } // Observable editTextChangeObservable .debounce(500, TimeUnit.MILLISECONDS) .map { it.toString() } // CharSequence를 String으로 변환 .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer) } override fun onDestroy() { super.onDestroy() disposeable.dispose() } }
하나하나 작게 나눠서 보자면 EditText의 textChanges()는 InitialValueObservable 타입이고
InitialValueObservable 는 Observable을 상속한다.
val editTextChangeObservable = binding.etRxEdit.textChanges()
@CheckResult fun TextView.textChanges(): InitialValueObservable<CharSequence> { return TextViewTextChangesObservable(this) }
abstract class InitialValueObservable<T> : Observable<T>() { ... 생략 ... }
즉, textChanges() Observable<CharSequence>를 상속한다고 봐도 된다.
editTextChangeObservable .debounce(500, TimeUnit.MILLISECONDS) .map { it.toString() } // CharSequence를 String으로 변환 .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(observer)
- debounce 는 특정 시간이 지난 후에 마지막으로 들어온 이벤트만 받을 수 있는 오퍼레이터다. 유저의 EditText가 0.5초동안 입력이 없다면 EditText의 CharSequence를 onNext로 방출한다.
- map은 방출된 데이터를 가공해서 방출시켜준다. (CharSequence를 그대로 사용할 수 없어서 String 타입으로 변환시켜줬다. )
- subscribeOn은 작업을 수행할 스레드를 지정한다.
- observeOn은 Observable이 생성하는 이벤트를 수신하고 처리할 스레드를 지정합니다.
- .subscribe { o -> ... }: Observable이 생성하는 이벤트를 구독합니다. 여기서는 텍스트 변경 이벤트가 발생할 때마다 호출됩니다. 이벤트 처리를 위해 람다 표현식이 사용되었으며, o는 텍스트 변경 이벤트에 대한 데이터입니다.
override fun onNext(t: String) { binding.tvRxEditResult.text = t // EditText 내용에 따른 TextView 변경 }
Observer를 만들고 onNext를 만들어서 edittext에 적힌 내용의 변화에 따라 textview가 변화하게 만들었다.
실시간 검색을구현하려면 네트워크 통신이나 기본 데이터를 미리 넣어놓고 EditText에 들어있는 String을 포함하는 List만 추려서 RecyclerView를 활용해서 검색어를 보여주는 방식으로 구현하면 되지만 이것 말고도 공부를 해야할게 많기 때문에 일단 이번 예제는 여기까지만 하려고 한다.
EditText 말고도 Button에서 사용해서 중복 클릭등을 막을 수 있다.
debounceButtonDisposable = binding.bntRxEditWoDebounce.clicks()// Debounce .debounce(1000, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ Log.d("DebounceClick", "Button clicked!") binding.tvRxEditClickWoDebounce.text = (++mDebounceButtonClicks).toString() }, { it.printStackTrace() }) throttleButtonDisposable = binding.bntRxEditWoThrottle.clicks() // throttleFirst .throttleFirst(1000, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ Log.d("ThrottleClick", "Button clicked!") binding.tvRxEditClickWoThrottle.text = (++mThrottleButtonClicks).toString() }, { it.printStackTrace() })
위에 코드는 Button 클릭과 debounce(), throttleFirst()를 사용해봤다.
Debounce와 ThrottleFirst의 차이는
Debounce는 여러번 클릭하면 시간초가 재갱신 되서 인식하기 때문에 1초이내로 여러번 클릭시 마지막 것만 인식한다.
ThrottleFirst는 여러번 클릭해도 1초마다 맨처음 데이터 방출된 것을 인식한다.
말로 하는 것 보다는 직접 사용해보면서 인식하는 것이 더 편할 것 같다.
'안드로이드 학습 > Android 기술면접 대비 코드' 카테고리의 다른 글
클린 아키텍처 준비 - 1 (0) 2025.04.24 안드로이드 비동기 처리 2-5 (네트워크 통신 - retrofit) (0) 2024.11.01 안드로이드 비동기 처리 2-3 (Operators : 연산자들) 코드편 (1) 2024.10.31 안드로이드 Rxjava 사용하기 (1) (0) 2024.03.06 Anr 예제 (0) 2024.01.23