0

In my project i am using clean architecture. The following code below is in my domain and data layers. Its an generic implementation so i don't have to repeat it for every model. This code works fine, i have tested it a million times. But after releasing my app, some phones (Huawei p8) are experiencing weird behavior from the database. Once i would call getList(X) from a certain activity the results are fine then i go to another activity make the same call but the response is empty. Sometimes i would receive an extra item that it is just full of nulls and default values. I am using the realm plugin 1.2. I really need to fix this bug. I would appreciate any sort of help.

@Override
public Observable getList(@NonNull GetRequest genericUseCaseRequest) {
    return mRepository.getListDynamically(genericUseCaseRequest.getUrl(), genericUseCaseRequest
            .getPresentationClass(), genericUseCaseRequest.getDataClass(), genericUseCaseRequest
            .isPersist(), genericUseCaseRequest.isShouldCache()).compose(applySchedulers());
}

@Override
public Observable<List> getListDynamically(@NonNull String url, Class presentationClass, @NonNull Class dataClass,
                                           boolean persist, boolean shouldCache) {
    try {
        return mDataStoreFactory.dynamically(url, true, mEntityMapperUtil.getDataMapper(dataClass))
                .dynamicGetList(url, presentationClass, dataClass, persist, shouldCache);
    } catch (IllegalAccessException e) {
        e.printStackTrace();
        return Observable.error(e);
    }
}

public DataStore dynamically(@NonNull String url, boolean isGet, EntityMapper entityDataMapper) throws IllegalAccessException {
    if (!url.isEmpty() && (!isGet || Utils.isNetworkAvailable(mContext)))
        return new CloudDataStore(new RestApiImpl(), mDataBaseManager, entityDataMapper);
    else if (mDataBaseManager == null)
        throw new IllegalAccessException(getInstance().getContext().getString(R.string.no_db));
    else
        return new DiskDataStore(mDataBaseManager, entityDataMapper);

}

@Override
public Observable<List> getAll(Class clazz) {
    return Observable.defer(() -> Observable.just(Realm.getDefaultInstance().where(clazz).findAll()));
}
Zeyad Gasser
  • 1,516
  • 21
  • 39

1 Answers1

1

This answer applies if you use Schedulers.io():

Have you considered closing your Realm instance that you open on your thread pool?

Because if you don't close the Realm (which you don't), then you'll experience version retention and your Realm instance in your background thread will never get updated again.

Also consider refreshing the Realm after opening the instance using this force-refresh workaround.

But also make sure you close the instance. In fact, considering you're trying to use a background thread for your query, you should consider using realm.copyFromRealm(realmResults) so that you can close the instance freely.

Community
  • 1
  • 1
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • Thanks for the response, but IllegalArgumentException: RealmObject is not valid, so it cannot be copied. Observable.defer(() -> { Realm realm = Realm.getDefaultInstance(); List finalResult = null; try { finalResult = Collections.singletonList(clazz.newInstance()); finalResult = realm.copyFromRealm(finalResult); } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace();} realm.close(); return Observable.just(finalResult); }) – Zeyad Gasser Oct 28 '16 at 23:30