Realm Blog

Realm Java 0.87이 이제 RxJava를 지원합니다!

어제 Realm Java 최신 버전을 이 사이트와 Maven에 릴리즈 했습니다. 이번 릴리즈는 RxJava를 위한 최고 수준의 API 지원을 포함합니다.

RxJava

RxJava 는 Netflix의 Reactive Extensions 라이브러리로 Observer pattern을 적용하였습니다. 시퀀스로 여러 오퍼레이터를 조합해서 Realm 데이터의 변화를 파악할 수 있습니다. 이제 RealmQueryRealmList를 제외한 모든 Realm 클래스를 Observable(https://github.com/ReactiveX/RxJava/wiki/Observable)로 보여줄 수 있습니다.

Realm의 Observable은 표준 리스너인 RealmChangeListener의 위에 구성됩니다. 따라서 모든 Observable은 리스너가 기존에 구독하고 있던 변경 사항과 같은 비중으로 객체를 발행할 수 있습니다.

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();

또한 Realm의 Async 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...
      }
  });

더 많은 예제를 RxJava example project에서 찾을 수 있습니다.

설정

RxJava가 우리 API의 최우선 사항이긴 하지만, 사용자가 사용을 수락해야 하는 옵트인 의존성을 지니므로 직접 build.gradle에서 RxJava를 추가해야 합니다. 사용자가 RxJava 버전을 직접 지정할 수 있으므로, RxJava를 사용하지 않는 메서드까지 포함되어서 프로젝트의 메서드 카운드가 불필요하게 증가하는 현상을 막을 수 있다는 장점이 있습니다.

dependencies {
  compile 'io.realm:realm-android:0.87.0'
  compile 'io.reactivex:rxjava:1.1.0'
}

Observable이 생성되는 방식을 커스텀할 수 있도록 RxObservableFactory라는 인터페이스도 추가했습니다. 기존의 커스텀 팩토리는 RealmConfiguration를 사용해서 설정하지만 Realm은 기본 팩토리인 RealmObservableFactory 클래스를 사용합니다. 이 또한 1.1.* RxJava를 지원합니다.

RealmConfiguration config = new RealmConfiguration.Builder(context)
  .rxFactory(new MyFactory())
  .build()

개발 진행 중인 사항

이번 릴리즈에 RxJava의 최초 지원 기능이 포함되지만, RealmQueryRealmList를 위한 Observable 지원이 아직 가능하지 않습니다. 추후 업데이트에 이들 기능을 추가할 예정입니다.

RealmObjectRealmResults가 스레드에 제한적이라는 점을 기억하세요. 즉, 한 스레드에서 로드한 Realm 객체를 다른 스레드에서 사용할 수 없습니다.

// Default pattern for loading data on a background thread
Observable.defer(new Func0<Observable<RealmResults<Person>>>() {
    @Override
    public Observable<RealmResults<Person>> call() {
        return realm.where(Person.class).findAll().asObservable();
    }
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<RealmResults<Person>>() {
    @Override
    public void call(RealmResults<Person> persons) {
        // Accessing persons here would crash.
    }
});

// Instead, use Realms Async API for the same effect
realm.where(Person.class).findAllAsync().asObservable()
  .subscribe(new Action1<RealmResults<Person>>() {
      @Override
      public void call(RealmResults<Person> persons) {
          // Show data in the UI
      }
  });

RealmObjectRealmResults는 끊임없이 Realm의 최신 데이터로 갱신되는 라이브 객체입니다. 일관성 유지에는 좋지만, 스레드 안정성이 있는 불변의 객체를 선호하는 RxJava의 모델과는 맞지 않습니다. 따라서 Realm.copyFromRealm() 메서드를 추가하여 Realm 데이터를 일반 자바 객체로 복사하고 안전하게 Realm에서 분리할 수 있도록 했습니다. 속도와 메모리 사용 측면에서 비용이 발생하지만 buffer()와 같은 오퍼레이터를 사용하기가 쉬워집니다.

// Get different versions of a person
realm.where(Person.class).findFirst().<Person>asObservable()
        .map(new Func1<Person, Person>() {
            @Override
            public Person call(Person person) {
                // Convert live object to a static copy
                return realm.copyFromRealm(person);
            }
        })
        .buffer(2)
        .subscribe(new Action1<List<Person>>() {
            @Override
            public void call(List<Person> persons) {
                // Without `map` and `copyFromRealm`, v1 and v2 would be the same
                Person v1 = persons.get(0);
                Person v2 = persons.get(1);
            }
        });

Thread handoff 와 관련된 이슈를 해결하여 추후 업데이트에 반영할 예정입니다.

자세한 사항은 changelog에서 볼 수 있습니다.


읽어주셔서 감사합니다. Realm과 함께 멋진 앱을 만들어 보세요! Stack Overflow, GitHub, Twitter를 통해 언제든지 저희와 소통할 수 있습니다.


Realm Team

Realm의 미션은 더 나은 앱을 빠르게 개발할 수 있도록 돕는 것입니다. 이를 위해 저희는 개발자들이 실시간 협업, 가상 현실, 라이브 데이터 동기화, 오프라인 경험, 메시징 등 정교하고 강력한 기능을 쉽게 개발할 수 있도록 하는 개발 도구와 플랫폼을 제공하고 있습니다.

저희는 모바일 인터넷이 수많은 사용자와 보다 많은 디바이스가 속한 개방형 네트워크와 이들 간의 실시간 상호 작용으로 진화할 것이라고 믿으며, 개발자가 이같은 방향으로 발전할 수 있도록 돕기 위해 저희 제품들을 개발하고 있습니다.

이런 개발 뉴스를 더 만나보세요