RxAndroid 시리즈의 마지막 글 입니다. 이번 시간에는 스케쥴러를 이용하는 법과 Retrofit, Realm 등의 다른 라이브러리와 함께 쓰일 때 어떻게 쓰일 수 있을지를 살펴보겠습니다.
스케쥴러
스케쥴러는 해당 옵저버블, 오퍼레이터, 서브스크라이버를 어떤 스레드에서 수행할지 결정하는 것입니다. 스케줄러가 어떤 부분을 맞게 되는지는 subscribeOn
과 observeOn
으로 지정합니다. 아래의 그림을 함께 봅시다.
observeOn
에서 지정한 스케쥴러는 이후에 따라오는 오퍼레이터, 서브스크라이버에 적용된 것을 볼 수 있습니다. 두번의 observeOn
에 의해 첫번째는 주황색 스케쥴러로 지정이 되어 모든 라인이 주황색으로 색칠이 되어 있고 두번째는 핑크색으로 스케쥴러를 지정한 것을 볼 수 있다.
subscribeOn
은 옵저버블의 스케쥴러를 바꾸는 것입니다. 옵저버블을 파란색으로 지정한 것을 볼 수 있습니다.
스케쥴러 목록
스케쥴러는 RxJava가 제공하는 스케쥴러와 RxAndroid가 제공하는 스케쥴러가 있습니다. 먼저 RxJava가 제공하는 스케쥴러를 살펴봅시다.
-
Schedulers.computation()
- 이벤트 룹에서 간단한 연산이나 콜백 처리를 위해서 쓰는 것입니다. I/O 처리를 여기에서 해서는 안됩니다. -
Schedulers.from(executor)
- 특정executor
를 스케쥴러로 사용합니다. -
Schedulers.immediate()
- 현재 스레드에서 즉시 수행합니다. -
Schedulers.io()
- 동기 I/O를 별도로 처리시켜 비동기 효율을 얻기 위한 스케줄러입니다. 자체적인 스레드 풀에 의존합니다. -
Schedulers.newThread()
- 항상 새로운 스레드를 만드는 스케쥴러입니다. -
Schedulers.trampoline()
- 큐에 있는 일이 끝나면 이어서 현재 스레드에서 수행하는 스케쥴러.
일부 오퍼레이터들은 자체적으로 어떤 스케쥴러를 사용할지 지정합니다. 예를 들어 buffer
오퍼레이터는 Schedulers.computation()
에 의존하며 repeat
은 Schedulers.trampoline()
를 사용합니다.
RxAndroid는 아래와 같은 스케쥴러를 추가합니다.
-
AndroidSchedulers.mainThread()
- 안드로이드의 UI 스레드에서 동작합니다. -
HandlerScheduler.from(handler)
- 특정 핸들러handler
에 의존하여 동작합니다.
안드로이드에 특화된 스케쥴러입니다. 보통은 RxAndroid가 제공하는 AndroidSchedulers.mainThread()
와 RxJava가 제공하는 Schedulers.io()
를 조합해서 Schedulers.io()
에서 수행한 결과를 AndroidSchedulers.mainThread()
에서 받아 UI에 반영하는 패턴등이 일반적으로 쓰입니다.
독립적으로 사용 가능한 스케쥴러
스케쥴러는 옵저버블, 오퍼레이터, 서브스크라이브 모델 밖에서 별도로 사용할 수 있습니다.
worker = Schedulers.newThread().createWorker();
worker.schedule(new Action0() {
@Override
public void call() {
realmJob();
}
});
realmJob
은 새로운 스레드에서 수행됩니다.
Retrofit에서의 응용
스퀘어의 인기 라이브러리 Retrofit도 RxAndroid를 지원합니다.
먼저 그래들 설정에 의존성을 추가합시다.
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta3'
compile 'io.reactivex:rxandroid:1.1.0'
RxAndroid를 Retrofit이 다룰 수 있게 하기 위해 RxJavaCallAdapterFactory를 콜 어댑터 팩토리로 추가합니다.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://realm.io/api/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
간단한 API를 통해 일반 버전과 Rx를 쓰는 버전의 차이를 살펴봅시다.
public interface RealmAPI {
@GET("user")
Call<User> getUser();
@GET("user")
Observable<User> getUserRx();
}
일반 버전인 getUser
는 콜백인 Call<User>
를 반환하고 Rx 버전은 Observable<User>
를 반환하여 이제는 익숙해진 Rx 방식으로 다룰 수 있습니다.
Realm에서 활용
Realm에서 Rx를 쓰는 것도 간단합니다.
Realm realm = Realm.getDefaultInstance();
RealmResults<Person> persons = realm.where(Person.class).findAll();
Person person = persons.first();
Observable<Realm> realmObservable = realm.asObservable();
Observable<RealmResults<Person>> resultsObservable = persons.asObservable();
Observable<Person> objectObservable = person.asObservable();
비동기 API에서도 사용할 수 있습니다.
realm.where(Person.class).equalTo("name", "John").findAllAsync().asObservable()
.filter(new Func1<RealmResults<Person>, Boolean>() {
@Override
public Boolean call(RealmResults<Person> persons) {
// Ignore unloaded results
return persons.isLoaded();
}
})
.subscribe(new Action1<RealmResults<Person>>() {
@Override
public void call(RealmResults<Person> persons) {
// Show persons...
}
});
마무리
기존의 자바 스크립트 라이브러리들은 비동기 처리가 필요한 경우 개별적인 API와 단순한 가공 정도를 제공했으나 Rx를 지원하는 현대적인 라이브러리에서는 다양한 방법으로 가공하여 사용할 수 있습니다. Retrofit이나 Realm도 그 중의 하나이고요.
앞으로 더 다양한 곳에서 더 멋진 방법으로 Rx를 사용해보세요.
컨텐츠에 대하여
이 컨텐츠는 저자의 허가 하에 이곳에서 공유합니다.