Search code examples
androidrealmdagger-2rx-android

Questions about Android with RxAndroid, Dagger 2 and Realm


I'm currently working on an App and wanted to use the current state of the art libaries for Android: RxAndroid, Dagger2 and Realm. I couldn't find good examples in the net, so I have to ask here.

1. Why should I use Observable as return type for Realm queries?

public Observable<Bla> getBla() {
    Bla b = realm.where(Bla.class).findFirst();
    return Observable.just(b);
}

In most cases Realm queries run on UIThread, so why I shound't just return the result as List instead of

Observable<List<Bla>>

Maybe someone knows a very good example with realm in this lib conbination?

2. Why I am able to inject a Service without mention a provider in the module. Is something wrong in my construction?

@Inject
TableService mTableService;

(Code below)

3. ServiceComponent needs Application from AppComponent, how to configure @Component correctly?

@Singleton
@Component(modules = {AppModule.class, ServiceModule.class})
public interface AppComponent {

    void inject(MainActivity activity);
}

@Singleton
@Component(modules = {AppModule.class, ServiceModule.class})
public interface ServiceComponent {

    void inject(MainActivity activity);
}

public class AppModule {

    Application mApplication;

    public AppModule(Application application) {
        mApplication = application;
    }

    @Provides
    @Singleton
    Application providesApplication() {
        return mApplication;
    }

    @Provides
    @Singleton
    RealmConfiguration provideRealmConfiguration(Application application) {
        return new RealmConfiguration.Builder(application)
               .schemaVersion(1)
               .deleteRealmIfMigrationNeeded()
               .build();
    }

    @Provides
    Realm provideRealm(RealmConfiguration realmConfiguration) {
        try {
            return Realm.getInstance(realmConfiguration);
        } catch (Exception cause) {
            Realm.deleteRealm(realmConfiguration);
            return Realm.getInstance(realmConfiguration);
        }
    }
}

@Module
public class ServiceModule {

    public ServiceModule() {
    }

    @Provides
    @Singleton
    GuestService provideGuestService(Realm realm) {
        return new GuestService(realm);
    }
}

public class Application extends android.app.Application {

    private AppComponent mAppComponent;

    @Override
    public void onCreate() {
        super.onCreate();

        mAppComponent = DaggerAppComponent.builder()
                .appModule(new AppModule(this))
                .build();

    }

    public AppComponent getAppComponent() {
        return mAppComponent;
    }
}

Thank you!


Solution

  • 1.) RealmResults<T> is auto-updating, and if you add a RealmChangeListener to your RealmResults, then it will be called whenever the underlying data has changed.

    private final RealmChangeListener listener = new RealmChangeListener() {
        @Override
        public void onChange(Object results) {
            notifyDataSetChanged();
        }
    };
    

    But when you call asObservable() on a RealmResults, then an Observable<RealmResults<T>> is created that automatically appends a RealmChangeListener that notifies you of changes, and removes it when you unsubscribe. You can look at the exact behavior if you check the default RealmObservableFactory implementation.

    So it really is a shorthand for adding a RealmChangeListener to your results so that you can update your views whenever.

    Subscription subscription = RxTextView.textChanges(editText).switchMap(charSequence -> 
        realm.where(SomeObject.class)
             .contains("searchField", charSequence.toString(), Case.INSENSITIVE)
             .findAllAsync()
             .asObservable())
    .filter(RealmResults::isLoaded) //
    .subscribe(objects -> adapter.updateData(objects));
    

    2.) You probably have specified an @Inject annotated constructor.

    public class TableService {
        @Inject
        Application application;
    
        @Inject
        public TableService() {
        }
    }
    

    3.) Typically you should have 1 component / scope.

    EDIT:

    1. Why should I use Observable as return type for Realm queries?
    public Observable<Bla> getBla() {
        Bla b = realm.where(Bla.class).findFirst();
        return Observable.just(b);
    }
    

    This doesn't really make sense to use with Realm, because it doesn't listen to changes.

    It's more reasonable to use

    public Observable<Blah> getBla() {
        Blah blah = realm.where(Blah.class).findFirst();
        if(blah == null) {
            return Observable.empty();
        } else {
            return blah.asObservable();
        }
    }
    

    Although personally I advise to use Observable<RealmResults<T>> because it is more reliable.

    3.) Not sure what you mean. Service Component is not working without @component appModule.class, but it should be in my understanding.

    There shouldn't even be a ServiceComponent. Just @Component SingletonComponent.