일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
- 개발
- 독서
- TabLayout and ViewPager
- 목표한번이뤄보자
- BottomNavigationViewEx
- 운동
- FrameLayout
- Android Universal Image Loader
- FragmentPagerAdapter
- overridePendingTraction
- 재태크
- 2020년 목표
- FragmentSatePagerAdapter
- Today
- Total
seops
[RxJava] 01. Basic Concepts for RxJava 본문
정말 오랜만에 블로그 포스팅을 한다.
그동안 많은 일들이 있었다.
지금 현재 실력을 테스트해보고, 부족한 부분을 느낄 수 있는 시간을 보냈다.
아무튼 오늘은 RxJava에 대한 첫 포스팅이다.
아래와 같은 순서대로, RxJava를 공부해보려고 한다.
1) '커니의 코틀린' 서적을 기반으로 개념 정리
2) 각 구성 요소 보충 (~ 01. Basic Concepts)
3) Github를 통해, RxJava 사용 예시 확인
4) Side-Project 적용 (~ 02. Apply and Development)
1. RxJava
"Reactive programming is programming with asynchronous data streams."
( 출처 : gist.github.com/staltz/868e7e9bc2a7b8c1f754 )
- Reactive Programming의 핵심은 모든 것을 비동기적인 데이터의 Stream으로 간주하고, Observer 패턴을 활용해, 비동기 이벤트를 처리하는 것
- Reative Progreamming의 핵심은 비동기(Async)와 Observer 패턴
- Rx는 ReactiveX의 약자로, 이벤트 기반 비동기 프로그래밍을 위한 라이브러리
- Reactive Extensions은 콜백 방식과 달리, 발생하는 이벤트를 이벤트 스트림에 전달, 이벤트 스트림을 관찰하다가 원하는 이벤트를 감지하면 이에 따른 동작을 수행하는 방식
- RxJava의 경우, 'Reactive Extensions' 라이브러리의 JVM 구현체
* 그러면 왜? 안드로이드에서 RxJava를 사용할까?
EX) DB에서 사용자 목록을 가져온 다음, 해당 결과를 뷰에 표시할 경우
ANS) 기본적으로 AsyncTask를 활용해, DB 작업을 한 뒤, 결과를 보여줄 것이다.
IF) 사용자가 GUEST가 아닌 경우만 표출한다면?
ANS) Adapter에 넣어주기 전, 사용자에 대한 조건을 추가한다던지, DB 쿼리를 변경
IF) 해당 작업을 수행하며, DB에 다른 작업을 동시에 수행한다면?
위와 같은 상황으로 인해, RxJava가 사용된다고 보면 될 것 같다.
즉! 아래와 같은 장점을 갖고 있다.
1) 비동기 이벤트를 매우 쉽고 빠르게 처리할 수 있다.
2) 이벤트나 데이터를 쉽게 가공 및 분배할 수 있다.
2. RxJava 내, 용어 정리
1) Observable
- 이벤트를 만들어 내는 주체로, 이벤트 Stream을 통해 만든 이벤트를 내보냄. (Emit)
- Observer 패턴에서 Subject와 동일한 기능을 수행
- Oberservable이 내보내는 Event를 받아, 어떤 작업을 하기 위해서는 subscribe()의 정의 필요
(Observable은 subscribe를 하는 시점부터, Event를 내보내기 시작)
2) Observer
- Observable에서 만든 이벤트에 반응하며, 이벤트를 받았을 때 수행할 작업을 정의
3) Operator (연산자)
- 인벤트 스트림을 통해 전달되는 이벤트를 변환
- 단순히 이벤트가 갖고 있는 값을 다른 형태로 변경하는 것뿐만 아니라, 특정 조건을 만족하는 이벤트만 이벤트 스트림에 흘려보낼 수도 있고, 이벤트의 개수를 바꿔주는 등 다양한 작업을 수행할 수 있다.
NO | Operator | Function |
1 | map | - 기존의 Observable로부터 받아들인 데이터를 새로운 형태로 변형하는데 사용 |
2 | flatMap | - map과의 차이점은 return 값이 Observable이라는 점 - flatmap 내, Observable.just를 통해 하나의 item에 대해 여러 개의 변형된 item 발행 - flatmpa 함수의 리턴 값을 보면 map 수행 후, merge를 통해, Observable Return * 동작성 추가 확인 해 볼 것 ( nittaku.tistory.com/205 ) |
* 연산자의 경우, 자주 사용하는 것들만 정리 예정
4) 스케줄러
- 스케줄러의 경우, 작업을 수행할 스레드르 지정
- observeOn() 메소드를 사용하여 스케줄러를 지정하며, 해당 메서드를 호출한 직후에 오는 연산자나 Observer에서 수행되는 작업이 앞의 observerOn()에서 지정한 스레드에서 실행
* 참고 - 안드로이드 메인 스레드에서 작업을 수행하기 위해 사용하는 스케줄러는 RxJava가 아닌, RxAndroid에 포함되어 있다. 이에 따라 안드로이드 애플리케이션에서 RxJaava를 사용하는 경우, RxAndroid도 함께 Dependency에 추가할 필요가 있다.
5) Disposable
- Disposable is a tool that can be used to control the lifecycle of an Observable.
- Disposable은 Observable을 subscribe 할 때, 생성되는 객체로 Observable에서 만드는 이벤트 스트림과 이에 필요한 리소스를 관리한다.
- Observable로 부터, 더 이상 이벤트를 받지 않으려면 Disposable을 통해 구독 해제하면 된다.
- Observable은 이를 감지하여, 자신을 subscribe 하고 있는 Observer가 더 이상 없을 경우, 이벤트를 만들기 위해 유지하고 있던 리소스 해제
* 참고 - 구독 시, 생성되는 Disposable 객체를 하나씩 관리할 수도 있지만 Composite Disposable을 사용하면 여러 개의 Disposable 객체를 하나의 객체에서 관리할 수 있다. 따라서 lifecycle에 따라 리소스를 적절히 관리해야 하는 Activity나 Fragment에서 Composite Disposable을 자주 사용한다.
3. RxJava의 사용 예
1) Retrofit을 통해 수신한 응답을 Observable 형태로 변환
* 참고 - Retroifit에서 받은 응답을 Observable 형태로 변환해주는 라이브러리인 adapter-rxjava2가 있다.
- API가 구현된 인터페이스에서 각 API의 반환 형태를 Observable로 바꿔야 한다.
- API를 호출할 수 있는 객체를 만들어주는 클래스 수정
private fun getAccessToken(code: String) {
disposables.add(api.getAccToken(
GITHUB_CLIENT_ID, GITHUB_CLIEN_SECRET, code)
// REST API를 통해 받은 응답에서 액세스 토큰만 추출
.map { it.accessToken }
/* 이후 수행되는 코드 모두 메인 스레드에서 실행되므로
* RxAndroid에서 제공하는 스케줄러인 AndroidSchedulers.mainThread()를 사용
*/
.observeOn(AndroidSchedulers.mainThread())
// 구독할 때 수행할 작업 구현
.doOnSubscribe { showProgress() }
// 스트림이 종료될 때, 수행할 작업 구현
.doOnTerminate { hideProgress() }
// Observable을 구독
.subscribe({ token ->
// API를 통해 액세스 코튼을 정상적으로 받았을 때, 처리할 작업 구현
authTokenProvider.updateToken(token)
launchMainActivity()
}) {
// 에러 블럭 (네트워크 오류나 데이터 처리 오류 등)
showError(it)
}
)
}
private fun searchRepository(query: String) {
disposables.add(api.searchRepository(query)
// Observable 형태로 결롸를 바꿔주기 위해, flatMap을 사용
.flatmap {
if(0 == it.totalCount) {
// 검색 결과가 없을 경우, 에러를 발생시켜 에러 메시지를 표출
Overvable.error(IllegalStateException("No search result"))
} else {
// 검색 결과 리스트를 다음 스트림으로 전달
Observable.just(it.items)
}
}
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe {
clearResults()
hideProgress()
showProgress()
}
.doOnTerminate { hideProgress() }
.subscribe({ items ->
// API를 통해 검색 결과를 정상적으로 받았을 때 처리할 작업을 구현
// 작업 중 오류가 발생하면, 해당 블록은 호출되지 않는다.
}) {
showError(it.message)
})
}
* 참고 - 연산자 Override를 통한, Disposable 관리
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
this.add(disposable)
}
2) RxBinding으로 UI 이벤트 처리
- 클릭 이벤트 / 체크박스 선택 이벤트 / 텍스트 필드에서 발생하는 텍스트 변경 이벤트와 같은 UI 이벤트를 Observable 형태로 받아 처리하는 방법
- ViewDisposables 프로퍼티를 추가하여, View 이벤트의 Disposable을 별도로 관리
- 검색을 수행했을 때, SearchView에 입력한 문자열은 RxSearchView.queryTextChangeEvent()를 사용하여, Observable 형태로 받을 수 있다.
private fun example() {
viewDisposables += RxSearchView.queryTextChangeEvents(searchView)
// 검색을 수행했을 때, 발생한 이벤트만 받는다.
.filter { it.isSubmitted }
// 이벤트에서 검색어 텍스트를 추출
.map { it.querText() }
// 빈 문자열이 아닌 검색어만 받음
.filter { it.isNotEmpty() }
// 검색어를 String 형태로 변환
.map { it.toString() }
.observeOn(AndroidSchedulers.mainThread())
.subscribe { query ->
updateTitle(query)
hideSoftKeyboard()
collapseSearchView()
searchRepository(query)
}
}
* 참고 - RxBinding 코틀린 확장 라이브러리를 적용하면, 아래와 같이 RxBinding에서 제공하는 함수를 각 UI 위젯의 인스턴스에서 직접 호출할 수 있다.
viewDisposables += searchView.queryTextChangeEvents()
.filter { it.isSubmitted }
.map { it.queryText() }
...
'Android > Android' 카테고리의 다른 글
[RxJava] 02. RxJava Open Source (0) | 2020.11.24 |
---|---|
[RecyclerView] Compare RecyclerView with ListView (1) | 2020.10.31 |
[RecyclerView] 2. SimpleRecyclerView (0) | 2020.10.22 |
[RecyclerView] 1. RecyclerView and DiffUtil (0) | 2020.10.20 |
[Callback] 2. Singleton Class (0) | 2020.10.12 |