본 포스팅은 RxJavaでOperators再入門 その1 포스팅을 번역했습니다.
제 일본어 실력으로 인하여 오역이나 오타가 발생할 수 있습니다.
실제 발표내용에 해당하는 슬라이드와 슬라이드의 일본어 부분만 번역
만 번역했다는 점 양해바랍니다.
이 기사는 RxJava Advent Calendar 2016의 10번째 기사입니다.
RxJava Advent Calendar에 참가했지만, 무엇을 쓸지 고민했고, 그러고 보니 나는 느닷없다고 생각되어 Operators을 다시 한번 공부하려고 생각했습니다.
그 첫 번째로는 분량이 많기 때문에 나누려고 생각했기 때문에 총 5회로 나눌 예정입니다.
그럼 첫 번째는 ReactiveX Introduction에 쓰여 있는 Creating Observables, Transforming Observables 두 가지에 대해 살펴보겠습니다.
주로 새로운 Observable
을 생성하는 오퍼레이터
스크래치로 Observable
을 만드는 연산자입니다.
Android에서는 비동기 통신에서 자주 보는 것이네요.
사용법은 다음과 같은 느낌입니다.
public class Create {
public static void main(String[] args) {
Observable.create(e -> {
Person person = new Person();
person.age = 100;
person.name = "nshiba";
e.onNext(person);
e.onComplete();
}).subscribe(System.out::println);
}
private static class Person {
int age;
String name;
@Override
public String toString() {
return name + ":" + String.valueOf(age);
}
}
}
출력
nshiba:100
onNext
에서 값을 전달하고, 종료 시에 onComplete를 부르는 느낌입니다.
또한, 오류의 경우에는 onError를 부릅니다.
defer
는 실행시키는 Observable
을 subscribe
할 때 생성하는 오퍼레이터입니다.
일반 create
는 그 자리에서 실행하는 Observable
을 만들지만, defer
는 Observable
의 생성 자체를 지연시킵니다.
Observable observable = Observable.defer(() -> observer -> {
observer.onNext("test");
observer.onComplete();
});
// 이 순간 defer 에서 새로운 Observable을 만들 수 있다
observable.subscribe(System.out::println);
이러한 Operator들은 한정된 용도로 주로 테스트용으로 사용된다고 생각합니다.
아무런 값은 없지만, 정상으로 종료하는 Observable
을 만듭니다.
즉 onComplete
만 호출됩니다.
아무런 값 없이 종료도 하지 않는 Observable
을 만듭니다.
아무런 값은 없지만, 지정한 에러를 내뱉는 Observable
을 만듭니다.
다양한 객체를 Observable로 변환합니다.
아마도 목록을 변환하는 경우가 많을 거라고 생각하기 때문에 샘플은 fromArray
로 만들어 보았습니다.
int[] nums = new int[] {1, 2, 3, 4, 5};
Observable
.fromArray(nums)
.subscribe(ints -> {
System.out.println("onNext");
System.out.println(Arrays.toString(ints));
},
throwable -> {
System.out.println("onError");
},
() -> {
System.out.println("onComplete");
});
출력
onNext
[1, 2, 3, 4, 5]
onComplete
지정한 일정한 간격으로 정숫값을 출력하는 Observable
을 생성합니다.
처음에 어느 정도 지연시킬지의 지정도 가능합니다.
Observable
.interval(1, TimeUnit.SECONDS)
.subscribe(System.out::print);
출력
01234567789...
직접 인수로 전달된 객체로 Observable
을 생성합니다.
또한, 복수로 전달된 경우는 그만큼 onNext
이 호출되어 복수 전달할 경우는 형이 통일되지 않아도 오류가 발생하지 않습니다.
Observable.just(3, 1, 5, 4, "test")
.subscribe(num -> {
System.out.println("onNext: " + num);
}, throwable -> {
System.out.println("onError");
}, () -> {
System.out.println("onComplete");
});
출력
onNext: 3
onNext: 1
onNext: 5
onNext: 4
onNext: test
onComplete
지정한 범위의 정수를 출력하는 Observable
을 생성합니다.
Observable.range(0, 10)
.subscribe(i -> {
System.out.println("onNext: " + i);
}, throwable -> {
System.out.println("onError");
}, () -> {
System.out.println("onComplete");
});
출력
onNext: 0
onNext: 1
onNext: 2
onNext: 3
onNext: 4
onNext: 5
onNext: 6
onNext: 7
onNext: 8
onNext: 9
onComplete
지정한 횟수 반복하는 Observable
을 생성합니다.
Observable.just(1, 2, 3, 4, 5)
.repeat(3)
.subscribe(i -> {
System.out.println("onNext: " + i);
}, throwable -> {
System.out.println("onError");
}, () -> {
System.out.println("onComplete");
});
출력
onNext: 1
onNext: 2
onNext: 3
onNext: 1
onNext: 2
onNext: 3
onNext: 1
onNext: 2
onNext: 3
onComplete
뭔가 계산한 값 등을 반환시키는 메소드의 반환 값을 출력하는 Observable
을 만듭니다.
Create
와 조금 닮은 부분이 있습니다만, 이쪽은 반환 값이 임의의 값이며, onNext
, onComplete
는 부르지 않는 것입니다.
Observable.fromCallable(() -> {
String str = "java";
str += ":" + "RxJava";
return str;
}).subscribe(System.out::println);
출력
java:RxJava
지정한 시간만큼 지연 후 값을 출력하는 Observable
을 만듭니다.
System.out.println(System.currentTimeMillis());
Observable.timer(3, TimeUnit.SECONDS)
.subscribe(aLong -> {
System.out.println(System.currentTimeMillis());
});
출력
1480975677330
1480975680651
지정한 간격으로 스트림을 나누어 리스트를 작성하는 오퍼레이터.
Observable.range(1, 5)
.buffer(3)
.subscribe(System.out::println);
출력
[1, 2, 3]
[4, 5]
스트림에 들어온 것을 처리하고 새로운 Observable
로 합성하는 오퍼레이터.
Observable.just(1, 2, 3)
.flatMap(i -> Observable.range(i, i * 2))
.subscribe(System.out::print);
출력
122345345678
스트림을 조건에 따라 그룹으로 나누는 오퍼레이터.
같은 그룹으로 하고 싶은 것에 같은 값을 반환하면 같은 그룹이 됩니다.
Observable.range(1, 10)
.groupBy(integer -> integer % 3)
.subscribe(integerIntegerGroupedObservable -> {
integerIntegerGroupedObservable.toList().subscribe(System.out::println);
});
출력
[3, 6, 9]
[1, 4, 7, 10]
[2, 5, 8]
스트림에 들어온 값을 변화시킬 수 있는 오퍼레이터.
위의 FlatMap
과의 차이는 FlatMap
은 Observable
을 반환하고 Map
은 값 자체를 반환합니다.
Observable.just(1,2,3)
.map(i -> i * 10)
.subscribe(System.out::println);
출력
10
20
30
리스트에 순차적으로 액세스해 나가는 Operator. 2개씩 액세스해 간다.
처음에는 첫 번째와 두 번째가 인수로 전달되고, 그 이후에는 이전 처리로 반환된 값이 첫 번째 인수·다음 값이 두 번째 인수로 전달된다.
subscribe
시에 전달된 값은 요소의 첫 번째 + 반환 값에 전달 된 값.
Observable.range(1, 5)
.scan((sum, item) -> sum + item)
.subscribe(System.out::println);
출력
1
3
6
10
15
지정한 간격으로 스트림을 나누어 분할된 스트림으로 새로운 Observable
을 만드는 오퍼레이터.
위의 Buffer
와 비슷하지만, Buffer
는 List<Integer>
를 출력하는 반면, Window
는 Observable<Integer>
를 출력한다.
Observable.range(1,5)
.window(3)
.subscribe(integerObservable -> {
integerObservable.toList().subscribe(System.out::println);
});
출력
[1, 2, 3]
[4, 5]
이런 식으로 다른 것도 할 수 있다면 좋겠습니다.
소스 코드는 공개하고 있습니다 -> nshiba/rx-samples
그리고, 뭔가 잘못된 점 등 있다면 댓글이나 github의 issue 등에 적어 주면 기쁩니다.
comments powered by Disqus
Subscribe to this blog via RSS.
LazyColumn/Row에서 동일한 Key를 사용하면 크래시가 발생하는 이유
Posted on 30 Nov 2024