[android] RxJava 연습

RxJava가 편하다고 말만듣고 해야지해야지 하다가 어려워 보여서 안하고 있었는데, 써보니 편한 게 많다.

글로만 읽었을 땐 이해가 안됐는데, 직접 해보니 감이 오더라.

 

읽어보면 도움되는 곳

 

 

정렬

Integer[] intList = {6, 1, 3, 5, 7, 0, -3};
Observable.from(intList).toSortedList().subscribe(n -> Log.i("int sort 1 ", "|" + n));
// int sort 1: |[-3, 0, 1, 3, 5, 6, 7]    

Observable.from(intList).toSortedList((i1, i2) -> i1.compareTo(i2)).subscribe(n -> Log.i("int sort 2 ", "|" + n));
// int sort 2: |[-3, 0, 1, 3, 5, 6, 7]

Observable.from(intList).toSortedList((i1, i2) -> -i1.compareTo(i2)).subscribe(n -> Log.i("int sort 3 ", "|" + n);
// int sort 3: |[7, 6, 5, 3, 1, 0, -3]

 

String[] strList = {"o", "T", "가나다", "a", "b", "c", "z", "h", "Q", "R", "토요일"};
Observable.from(strList).toSortedList().subscribe(n -> Log.i("str sort 1 ", "|" + n));
// str sort 1: |[Q, R, T, a, b, c, h, o, z, 가나다, 토요일]

Observable.from(strList).toSortedList((s1, s2) -> s1.compareTo(s2)).subscribe(n -> Log.i("str sort 2 ", "|" + n));
// str sort 2: |[Q, R, T, a, b, c, h, o, z, 가나다, 토요일]

Observable.from(strList).toSortedList((s1, s2) -> -s1.compareTo(s2)).subscribe(n -> Log.i("str sort 3 ", "|" + n));
// str sort 3: |[토요일, 가나다, z, o, h, c, b, a, T, R, Q]

 

 

first, last, take, takeLast

String[] strings = new String[0];
Observable.from(strings).first().subscribe(s -> Log.i("empty ", "|" + s));
// rx.exceptions.OnErrorNotImplementedException: Sequence contains no elements

처음과 마지막을 가져오는 first(), last() 가 있는데, 빈 배열일 때 호출하면 오류가 난다.

 

String[] strings = new String[0];
Observable<String> so = Observable.from(strings);

Log.i("=", "=== 1 === ");
so.take(1).subscribe(s -> Log.i("empty array 1 ", "|" + s));

Log.i("=", "=== 2 === ");
so.takeLast(1).subscribe(s -> Log.i("empty array 2 ", "|" + s));

Log.i("=", "=== 3 === ");
so.first().subscribe(s -> Log.i("empty array 3 ", "|" + s), e -> {}, () -> {});

Log.i("=", "=== end === ");


// === 1 === 
// === 2 === 
// === 3 === 
// === end ===

first 대신 take(1), last 대신 takeLast(1)을 쓰거나, subscribe에 onError, onCompleted 를 적어주면 된다.

 

 

flatmap

ruby의 flatten 같은 느낌인데, 변환과정에서 배열로 리턴된걸 다시 observable로 만들어 준다.

String str = "qwer-asdf-zxcv";
Observable.just(str)
          .map(s -> s.split("-"))
          .flatMap(Observable::from)
          .take(2)
          .takeLast(1)
          .subscribe(s -> Log.i("split", "|" + s));
// split: |asdf

 

 

비동기

Observable.range(1, 9999).subscribe(t -> {}, e -> {}, () -> Log.i("", "9999 끝"));
Observable.range(1, 100).subscribe(t -> {}, e -> {}, () -> Log.i("", "100 끝"));
// 9999 끝
// 100 끝

그냥 이렇게 하면 일반적인 동작을 한다.

 

Observable.range(1, 9999).subscribeOn(Schedulers.newThread()).subscribe(t -> {}, e -> {}, () -> Log.i("", "9999 끝"));
Observable.range(1, 100).subscribeOn(Schedulers.newThread()).subscribe(t -> {}, e -> {}, () -> Log.i("",  "100 끝"));
// 100 끝
// 9999 끝

subscribeOn(Schedulers.newthread()) 를 달아주면 비동기로 호출이 된다.

 

 

observeOn

만약 비동기 혹은 다른 이유로 뷰를 건들일 때

Observable.just("111").subscribeOn(Schedulers.newThread()).subscribe(t -> tv.setText(t));
// rx.exceptions.OnErrorNotImplementedException: Only the original thread that created a view hierarchy can touch its views.

라는 에러가 나면

.observeOn(AndroidSchedulers.mainThread())

를 붙여주면 된다.

Observable.just("111").subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread()).subscribe(t -> tv.setText(t));

 

 

================ 여기서 부터는 RxJava 2.x 로 작성됨 ============

groupBy

배열에서 고유한 값만 가져오고 있을 때 사용하면 좋다. 특히 날짜별로 정렬할 때 사용하면 아주 편하다.

private void groupBy() {
  Integer[] array = {1, 1, 1, 2, 3, 4, 5, 6, 6, 4, 34, 3, 2, 1};
  Observable<Integer> ob = Observable.fromArray(array);
  Observable ob2 = ob.groupBy((Function<Integer, Object>) i -> i).map(i -> i.getKey());

  ob2.subscribe(i -> Log.i("MainActivity : groupBy", "고유값 " + i));
// 고유값 1
// 고유값 2
// 고유값 3
// 고유값 4
// 고유값 5
// 고유값 6
// 고유값 34
  

  ob2.subscribe(i -> {
    Log.i("MainActivity : groupBy", "=======" + i + "==========");
    ob.filter(i::equals)
        .subscribe(i2 -> Log.i("MainActivity : groupBy", "filter: " + i2.toString()));
  });
// =======1==========
// filter: 1
// filter: 1
// filter: 1
// filter: 1
// =======2==========
// filter: 2
// filter: 2
// =======3==========
// filter: 3
// filter: 3
// =======4==========
// filter: 4
// filter: 4
// =======5==========
// filter: 5
// =======6==========
// filter: 6
// filter: 6
// =======34==========
// filter: 34
}