2017년 6월 4일 일요일

[STUDY] RxAndroid Part 5 (Observable 변형/가공/합성 - map/flatMap/zip)

[목차]==================================================
1. Observable 변형 및 가공 
1) map()
2) flatMap()
3) Filter()
4) 기타
2. Observable 합성
1) zip()
2) 기타
======================================================


1. Observable 변형 및 가공
발생되는 이벤트를 다른 형태로 변형하기를 원하실 수도 있습니다.
가장 많이 사용되는건 map 과 flatMap 입니다.

1) map()
map() 함수를 사용하여 전달받은 이벤트를 다른값으로 변경합니다.
     public void map() {
        Observable.from(new String[] { "개미", "매", "마루" })
            .map(text -> "** " + text + " **")
            .subscribe(
                text -> System.out.println("onNext : " + text),
                e -> System.out.println("onError"),
                () -> System.out.println("onCompleted"));
    }
     // 결과
    onNext : ** 개미 **
    onNext : ** 매 **
    onNext : ** 마루 **
    onCompleted

Observable.just("hello world")
        .map(new Func1<String, String>() {
            @Override
            public String call(String s) {
                return s + "RxJava";
            }
        })
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.i(TAG, ">>> onNextAction  : " + s);
            }
        })

2) flatMap()
flatMap()은 전달받은 이벤트로부터 다른 Observable 들을 생성하고, 그 Observable 들에서 발생한 이벤트들을 쭉 펼쳐서 전파합니다.
    public void flatMap() {
        Observable.from(new String[] { "개미", "매", "마루" })
            .flatMap(
                text -> Observable.from(new String[] { text + " 사랑합니다.", text + " 고맙습니다." })

            )
            .subscribe(
                text -> System.out.println("onNext : " + text),
                e -> System.out.println("onError"),
                () -> System.out.println("onCompleted"));
    }
    // 결과
    onNext : 개미 사랑합니다.
    onNext : 개미 고맙습니다.
    onNext : 매 사랑합니다.
    onNext : 매 고맙습니다.
    onNext : 마루 사랑합니다.
    onNext : 마루 고맙습니다.
    onCompleted

3) Filter()
데이터 filter 역할
  Observable.just("hello world")
        .filter(new Func1<String, Boolean>() {
            @Override
            public Boolean call(String s) {
                if (s.contains("hello")) {
                    return true;
                } else {
                    return false;
                }
            }
        })
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.i(TAG, ">>> onNextAction  : " + s);
            }
        });
위와 같이 filter 함수를 보면 observable 을 통해서 넘어온 데이터에 hello 가 포함되어있는지를 확인 하고 있다.
포함되어 있지 않으면 false 가 넘어가게 되어서 subscribe 가 호출되지 않는다.

4) 기타
map() / 특정 Func 객체를 받아서 옵저버블이 발행하는 모든 값에 Func 객체를 적용
flatMap() / 모든 발행한 값을 하나의 최종 옵저버블로 병합하는 방식으로 시퀀스를 플랫하게 만드는 방법을 제공
concatMap() / 발행한 값을 병합하는 대신, 발행한 값을 연쇄적으로 연결할 수 있는 플랫한 함수를 제공해 flatMap()의 인터리빙 문제를 해결
flatMapIterable() / 소스 아이템과 생성된 옵저버블 간에 쌍이 되는 것이 아니라 소스 아이템과 생성된 이터러블이 한 쌍이 됨
switchMap() / 소스 옵저버블에서 새로운 아이템을 발행할 때마다 먼저 발행한 아이템이 생성한 옵저버블의 구독을 해지하고 미러링을 중지한 다음 새로 발행한 아이템을 미러링
scan() / 옵저버블이 발행하는 각 아이템에 함수를 적용해 함수 결과를 계산한 다음, 결과를 옵저버블 시퀀스에 다시 주입해 다음번에 발행되는 값과 함께 사용하기 위해 대기
groupBy() / 특정 기준에 따라 리스트의 요소를 분류하는 함수
buffer() / 소스 옵저버블을 새로운 옵저버블로 변환하며, 새로운 옵저버블은 하나의 아이템이 아닌 리스트 형태로 값을 발행
window() / buffer()와 유사하지만, 리스트가 아닌 옵저버블을 발행
cast() / map() 연산자의 특수 버전으로 소스 옵저버블의 각 아이템을 다른 Class로 캐스팅해 새로운 타입으로 변환

filter(return E) / return E값이 true일 때만 값이 발행되고 옵저버에게 전달
take(n) / 옵저버블을 1번째부터 n번째까지만 발행 -> 쉽게 알 수 있는 아이템의 소규모 그룹을 얻기 위해 사용
takeLast(n) / 옵저버블의 마지막 요소 n개만큼 발행
distinct() / 특정 값을 단 한번만 처리
distinctUntilChanged() / 모든 중복 값은 무시하고 새로운 값만 발행
first() / 옵저버블이 발행한 요소에서 첫번째 요소만을 발행
last() / 옵저버블이 발행한 요소에서 마지막 요소만을 발행
skip(n) / 옵저버블이 발행한 요소에서 처음 n개의 요소를 숨김
skipLast(n) / 옵저버블이 발행한 요소에서 마지막 n개의 요소를 숨김
elementAt(n) / 시퀀스에서 n번째 요소만을 발행한 후 시퀀스를 완료 (elementAtOrDefault() 는 해당 시퀀스가 없을 경우도 포함)
sample(n, time) / n(time)마다 마지막으로 발행된 값을 발행 / 첫 번째 아이템을 발행시키기 위해서는 throttleFirst() 사용
timeout(n, time) / 옵저버블 시퀀스 소스에 반영하며 지정한 시간 내에 아무런 값을 받지 못할 경우 에러를 발행
debounce(n, time) / 옵저버블에서 아이템이 발행된 다음 바로 뒤따라서 발행된 아이템을 필터링하고, 옵저버블에서 일정 시간 동안 다른 아이템이 발행되지 않으면 아이템을 발행



2. Observable 합성
두개 이상의 Observable 을 합성해야 하는 경우도 있다.
data-flow 에 기반한 개발에서 매우 자주 언급되고 사용되기는 하지만, 일반적인 비동기작업에서는 자주 사용하는 개념은 아니다.
하지만 알고 있으면 종종 사용하게되는 유용한 도구들이니 한번쯤 살펴보고 넘어가시는걸 추천

1) zip()
네트워크 작업으로 사용자의 프로필과 프로필 이미지를 동시에 요청하고, 그 결과를 합성해서 화면에 표현해준다거나 하는 형태의 작업이 필요한 경우 zip() 유용하게 사용
     public void zip() {
        Observable.zip(
            Observable.just("개미"),
            Observable.just("gaemi.jpg"),
            (profile, image) -> "프로필 : " + profile + ", 이미지 : " + image
        ).subscribe(
            print -> System.out.println("onNext : " + print),
            e -> System.out.println("onError"),
            () -> System.out.println("onCompleted")
        );
    }
     // 결과
    onNext : 프로필 : 개미, 이미지 : gaemi.jpg
    onCompleted

2) 기타
merge() / 옵저버블이 발행한 아이템을 병합하는 방식으로 2개 이상의 옵저버블을 결합
zip() / 여러 옵저버블에서 발행한 아이템을 결합하고, 특정한 함수인 Func에 따라 아이템을 변환한 다음 새로운 값을 발행
join() / merge()와 zip()은 발행한 아이템의 도메인에서 동작하기 때문에 값을 처리하는 방법을 결정하기 전에 시간을 고려해야 하는 시나리오가 있을 수 있는데, 해당 함수를 사용함으로 타임 윈도와 함께 동작해 두 옵저버블의 아이템을 결합 / 간단한 상황에서는 문자열과 동작하며, 단순히 발행한 문자열열을 하나의 최종 문자열로 조인하는 연산자도 있다.
combineLatest() / zip()은 두 옵저버블의 가장 최근 언집된 아이템에서 동작하는 대신, 해당 함수는 가장 최근에 발행한 아이템에서 동작
and(), then(), when()  /해당 함수들을 사용함으로써 패턴과 플랜 같은 구조체를 사용해 발행한 아이템을 결합
switch() / 옵저버블을 발행하는 옵저버블을 가장 최근 발행한 옵저버블을 발행하는 옵저버블로 변환
startWith() / 옵저버블이 아이템 발행을 시작하기 전에 인자로 전달받은 아이템의 시퀀스로 발행
 


출처 : 인터넷에서 RxAndroid 검색하여 필요한 정보를 다양한 사이트에서 종합하여 작성된 것입니다. 많은 사이트 내용을 종합하여 공부하여 작성하다보니 일일이 나열하지 못하였습니다. ㅈㅅ(_ _) 이글은 자유롭게 퍼 가셔서 도움이 되었으면 좋겠습니다. 감사합니다.

댓글 없음:

댓글 쓰기