Search code examples
androidrealmrx-java2dagger-2

Realm access from incorrect thread in rx and dagger


I know this question asks a lot but i am confused by reading this question.In my project i am using dagger, rx and realm in mvp pattern.I have an application with a LoginActivity that when the user login correctly, the user information that comes from server store in realm in this page and user jumps to MainActivity.In MainActivity i want this user info but i got this error:

java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.

I know that :

Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.

In my Appliction class i have initialized DaggerAplicationComponnet.I have applicationModule:

@AppScope
@Component(modules = {ApplicationModule.class, NetworkModule.class , AppRealmModule.class})
public interface ApplicationComponent {
    Realm getRealm();
    ...
}

and AppRealmModule:

@Module
public class AppRealmModule {

    @Provides
    @AppScope
    Realm provideRealm (Context context) {
        Realm.init(context);
        RealmConfiguration realmConfiguration = new RealmConfiguration.Builder()
                .deleteRealmIfMigrationNeeded()
                .name("Payeshdb")
                .build();
        Realm.setDefaultConfiguration(realmConfiguration);
        return Realm.getDefaultInstance();
    }

That means , i create realm instance on ui thread.Now in MainActivity i have read realm:

@Override
public Observable<User> findUser() {
    return Observable.create(new ObservableOnSubscribe<User>() {
        @Override
        public void subscribe(ObservableEmitter<User> emitter) throws Exception {
            try {
                User user = realm.where(User.class).findFirst();
                User user1 = realm.copyFromRealm(user);
                emitter.onNext(user1);
                emitter.onComplete();

            }catch (Exception e) {
                emitter.onError(e);
            }
        }
    });
}

Now, in presenter i am using rx in this way:

userRepository.findUser()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new DisposableObserver<User>() {
                    @Override
                    public void onNext(User user) {

                    }

                    @Override
                    public void onError(Throwable e) {
                      // got error: Realm access from incorrect thread.
                    }

                    @Override
                    public void onComplete() {

                    }
                });

this is a place that i got above error. In some post i have read this:

Use copyFromRealm to get the data from realm which will return them as plain objects rather than realm objects.

And i do that but i still got error.

Is it possible initialize realm with dagger and use different thread for crud operation?

What is your suggestion?


Solution

  • @Override
    public Observable<User> findUser() {
      return Observable.create(new ObservableOnSubscribe<User>() {
        @Override
        public void subscribe(ObservableEmitter<User> emitter) throws Exception {
            try(Realm realm = Realm.getDefaultInstance()) {
                realm.refresh();
                User user = realm.where(User.class).findFirst();
                User user1 = realm.copyFromRealm(user);
                emitter.onNext(user1);
                emitter.onComplete();
            } catch (Exception e) {
                emitter.onError(e);
            }
        }
      });
    }