2017-01-31 5 views
1

Я пытаюсь реализовать класс DBService, который работает на фоновом потоке, который имеет метод Observable getWhere (@NonNull RealmQuery realmQuery). Поскольку я знаю, что мне нужно создать экземпляр Realm в том же потоке, я обращаюсь к нему. Итак, я нашел способ создать RealmQuery в фоновом потоке, но это ужасный взлом. Все другие мои попытки привели к java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were createdСоздайте RealmQuery в фоновом потоке

Presenter Код:

.
dataUseCase.searchDisk(getRealmQuery(RepoRealm.class) 
       .equalTo("owner.login", userLogin), RepoRealm.class) 


public static getRealmQuery RealmQuery(Class clazz) { // horrible hack 
    if (handler == null) 
     handler = new Handler(getHandlerThread().getLooper()); 
    handler.postAtFrontOfQueue(() -> realmQuery = RealmQuery.createQuery(Realm.getDefaultInstance(), clazz)); 
    while (true) if (realmQuery != null) break; 
    return realmQuery; 
} 

getHandlerThread() getLooper() возвращает свой единственный фоновый поток.

DBService:

public Observable<List> getWhere(@NonNull RealmQuery realmQuery) { 
    return Observable.defer(() -> { 
     Realm realm = Realm.getDefaultInstance(); 
     return realmQuery.findAll().asObservable() 
       .filter(results -> ((RealmResults) results).isLoaded()) 
       .map(o -> realm.copyFromRealm((RealmResults) o)) 
       .doOnUnsubscribe(() -> closeRealm(realm)); 
    }); 
} 

Я пробовал другие подходы, но я всегда получаю исключение доступа Realm от неправильного потока.

Хотя мое решение работает, но оно может заморозить мое приложение какое-то время, пока не будет создан realmQuery, чего я бы хотел избежать. Какие-либо предложения? заранее спасибо.

+0

Да, не используйте 'handler.postAtFrontOfQueue)' и бросать случайные Realm-управляемые объекты между потоками, особенно если вы используете RxJava, который уже имеет 'observeOn (AndroidSchedulers.mainThread())', которые довольно многое делает то же самое – EpicPandaForce

+0

PS вы открываете новый экземпляр Realm, который вы никогда не закрываете – EpicPandaForce

+0

Чтобы ответить на этот вопрос, вам необходимо знать, что именно вы делаете с 'RealmResults ' вы получаете из Realm **. – EpicPandaForce

ответ

1
public <T extends RealmModel> Observable<List<T>> getWhere(RealmQueryProvider<T> queryFactory) { 
    return Observable.defer(() -> { 
     Realm realm = Realm.getDefaultInstance(); 
     return queryFactory.create(realm).asObservable() 
       .filter(results -> ((RealmResults<T>) results).isLoaded()) 
       .map(o -> realm.copyFromRealm((RealmResults<T>) o)) 
       .doOnUnsubscribe(() -> closeRealm(realm)); 
    }); 
} 

public interface RealmQueryProvider<T extends RealmModel> { 
    RealmResults<T> create(Realm realm); 
} 

// example 
Observable<List<Dog>> dogs = dbService.getWhere((realm) -> realm.where(Dog.class).findAll()); 
+0

Этот код не компилируется. queryFactory.create (realm) .asObservable() create (realm) не имеет asObservable как метод –

+0

Должны были результаты, как показано моим примером – EpicPandaForce

+0

Да, я понял это. Я пытался это сделать, и это работает. Но я столкнулся с проблемой производительности. его замораживание моего моего UIThread, но я все еще проверяю, если его что-то еще –