[출처] http://reactivex.io/
RxJava
ReactiveX 를 Java 언어를 빌려 표현한것. ReactiveX 는 Observable Stream을 가지고 비동기적 프로그래밍을 할수 있는 API.
예시 코드)
1 2 3 4 5 6 7 8 9 10 11 12 13 | Observable<String> myObservable = Observable.from(new String[]{"Hello", "world!"}); myObservable.subscribe(new Action1<String>() { @Override public void call(String s) { System.out.println(s); } }); | cs |
처음 이렇게 봤을 때, 코드는 이해했지만, 머릿속에 든 생각은 '그래서 뭐?' 였다.
이걸 왜 써야하는 것이며, 뭐가 깔끔한 것이고, 뭐가 어떻다는 건지....
왜 ReactiveX 를 써야하나? 하고 글을 검색하면, 정말 수 많은 글이 올라 온다.
근데 사용법만 알려주고 있고 '왜'는 왜 안말해주는 걸까? 아니, '왜'를 엄청 길고 거창하게 표현한다.
나의 '왜' 경우는, 당연히!, 위에서 쓰자고 하니까...
RxJava 를 사용하여 한 프로젝트를 마친후 소감은.. 그러니까... 굳이 이렇게 덕지덕지 할 필요가 있는 건가...싶지만 그래도 편한 건 알겠다.(솔직히 편한가 싶은데, 다들 편하다고 하니.. 그리고 적응중이라 이렇게 느낄 수도 있고)
쓰레드를 따로 돌리는 것도 간단하고, 연쇄로 Operator 를 쓸 수 있고. 그러다가.. 어어 내가 어디까지 뭘 쓴거지...?
글을 여러개 읽어 보고 하지만, 결국 실제로 사용해보기 전까지는 익숙해지지가 않는다.
그리고 지금도 언제는 RxJava 를 써서 하고, 언제는 안 쓰고 할지 감이 안 온다.
Build pattern 처럼, 연쇄적으로 operator 를 사용하니 코드가 깔끔해지는 것 같으면서도,
항상 과도하게 이걸 사용하고 있는 건 아닐까 하는 생각이 든다.
자주 사용했던 상황
- 간단한 네트워크 통신 할 때
1 2 3 4 5 6 7 8 9 10 11 12 | Single.just(client) .subscribeOn(Schedulers.io()) .timeout(15, TimeUnit.SECONDS) .map { it.connect("host address") it.login("ID","PASSWORD") it} .subscribe({ // handling result of request },{ it.printStackTrace() }) |
- 2개 이상의 서로 연관 없는 변수들의 값을 가지고 계산을 해야할 때
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Observables.combineLatest(appVersionObservable(), clientApiObservable()) { current, latest -> latestVersion = latest.name.split("_")[1].substring(1) // *.* hasNewVersionSubject.onNext(hasNewVersion(current.min(), latestVersion))} .subscribe({ // Unit type is come },{ it.printStackTrace() }) .addTo(disposable) Observable.merge(connectedDeviceObservable, connectionStateObservable) .flatMapSingle { rxBluetooth.connectAsClient(it, "UUID") } .subscribe({ bluetoothSocket -> // Someting to do with bluetoothSocket }, { it.printStackTrace() }) .addTo(disposable) | cs |
위 두 상황이 제일 많이 사용되었다, 사실 압도적으로 두번째가 많이 사용되었다.
자주 사용한 Operator (combineLatest, merge, filter)
combineLatest
두 개의 Observable 중 하나가 항목을 배출할 때 배출된 마지막 항목과 다른 한 Observable이 배출한 항목을 결합한 후 함수를 적용하여 실행 후 실행된 결과를 배출한다
1. 2개의 Observable 모두가 항목 배출을 끝낸다.(2개중 마지막 1개의 배출을 받을 때 까지 기다림)
1 2 3 | observable1 -> data1 observable2 -> data2 | cs |
2. 받은 2개의 데이터를 가공(data1 과 data2 를 가지고 something 을 가공)
1 | f(data1,data2) -> something | cs |
3. 가공된 데이터를 배출하게되는 Observable 이 됨
1 | Observable(something) | cs |
4. 이렇게 생성된 Observable 을 가지고 나머지 연산 및 구독을 함
1 2 3 4 5 6 7 | Observables.combineLatest(observable1, observable2) { data1, data2 -> f(data1, data2) } .subscribe({ something -> // Todo someting },{ it.printStackTrace() }) .addTo(disposable) | cs |
merge
여러개의 Observable들(같은 타입을 배출)이 배출하는 항목들을 병합하여 하나의 Observable로 만든다
1. 같은 타입의 데이터를 배출 하는 복수개의 Observable 들
1 2 3 4 5 6 7 | observable1 -> data1 // (타입은 T) observable2 -> data2 // (타입은 T) observable3 -> data3 // (타입은 T) observable4 -> data4 // (타입은 T) | cs |
2. Observable1,2,3,4 가 발행하는 것을 한개의 Observable 로 발행
1 | (observable1, observable2, observable3, observable4) -> observableN | cs |
3. 이렇게 생성된 Observable 을 가지고 나머지 연산 및 구독
1 2 3 4 5 6 7 | Observable.merge(observable1, observable2, observable3, observable4) .subscribe({ data -> // data's type is T // Someting to do with data }, { it.printStackTrace() }) .addTo(disposable) | cs |
filter
테스트 조건을 만족하는 항목들만 배출한다.
1 2 3 4 5 6 7 | observable.filter { data -> data.hasToFiltering() } // data will be filtered by the condition(data.hasToFiltering()). .subscribe({ data -> // data is filtered // Someting to do with data }, { it.printStackTrace() }) .addTo(disposable) | cs |
참고 사이트
- http://reactivex.io/
- https://github.com/ReactiveX/RxJava
'Android' 카테고리의 다른 글
신기술이라고 막 좋아하다가 탈랄지도....(Kotiln, RxJava, MVVM, Databinding 등등) - 3 (0) | 2019.01.18 |
---|---|
신기술이라고 막 좋아하다가 탈랄지도....(Kotiln, RxJava, MVVM, Databinding 등등) - 1 (2) | 2018.12.24 |