D Yao.
D Yao.

Reputation: 401

Using Generics with Realm + RxJava

I'm trying to isolate my layers when building out an application that is going to be maintained for several years. I'm using Realm as a database, Retrofit as a networking layer, and RxJava/RxAndroid as the communication layer in the MVP/MVVM architecture. In the future, I want whoever takes up this project to be able to simply swap out Realm or swap out Retrofit, say if a better library comes out that lends itself to future improvements.

So, to that end, I'm trying to build a generic database interface, and then build my concrete Realm implementation on top of it.

I have a IDatabaseManager interface defined as follows:

public interface IDatabaseManager<E extends AbstractList<? extends T>, T> {
    void save(T object);
    Observable<E> getAsObservable(Class<?> type);
}

The idea being, I want the database manager to have type E which is some list/collection of some class '?' which extends some base object (for those ORMs which require you to extends some base class).

Then, I have my concrete implementation, which utilizes realm:

public class RealmManager implements IDatabaseManager<RealmResults<? extends RealmObject>, RealmObject> {

  @Override
  void save(RealmObject object) {
    //implementation works
  }

  @Override
  Observable<RealmResults<? extends RealmObject>> getAsObservable(Class<?> type) {
    Realm realm = realm.getDefaultInstance();
    return realm.where(type).findAllAsync().asObservable();
  }
}

However, I'm getting an error on "type" that:

where (java.lang.Class<E>) in Realm cannot be applied
to    (java.lang.Class<capture<?>>) 

reason: inference variable E has incompatible bounds:
equality constraints: capture of ?
upper bounds: Realm Model

Realm performs queries by taking in a class of the object collection you're querying, where that object must extend RealmObject (abstract), or implement RealmModel (interface), but they are supposed to be interchangeable.

Any help here? I think I'm just messing up some syntax here and I just can't figure out how I can fix it =/

Upvotes: 1

Views: 637

Answers (1)

EpicPandaForce
EpicPandaForce

Reputation: 81539

Your initial question is answered by

  @Override
  <T extends RealmModel> Observable<RealmResults<T> getAsObservable(Class<T> type) {
    Realm realm = realm.getDefaultInstance();
    return realm.where(type).findAllAsync().asObservable();
  }

But in reality, if you want to be able to "simply swap out Realm", you'll have to give up zero-copy evaluation and live-autoupdate, in favor of copying out the Realm objects.

return Observable.defer(() -> {
    try(Realm realm = Realm.getDefaultInstance()) {
        return Observable.just(realm.copyFromRealm(realm.where(type).findAll()));
    }
}).subscribeOn(Schedulers.io());

(although that kinda defeats the purpose if you ask me - after all, Realm was designed so that you don't need to copy everything out to memory)

Upvotes: 1

Related Questions