【问题标题】:Create a RealmQuery on background thread在后台线程上创建 RealmQuery
【发布时间】:2017-01-31 14:51:16
【问题描述】:

我正在尝试实现一个 DBService 类,它在后台线程上运行,它有一个 Observable getWhere(@NonNull RealmQuery realmQuery) 方法。据我所知,我需要在访问它的同一线程上创建 Realm 实例。所以,我找到了一种在后台线程上创建 RealmQuery 的方法,但它是一个可怕的 hack。我所有其他尝试都导致java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created

演示者代码:

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() 返回我唯一的后台线程。

数据库服务:

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));
    });
}

我尝试了其他方法,但我总是收到来自错误线程的领域访问异常。

虽然我的解决方案有效,但它可以冻结我的应用程序一段时间,直到创建 realmQuery,这是我想避免的。有什么建议么?提前致谢。

【问题讨论】:

  • 是的,不要使用 handler.postAtFrontOfQueue) 并在线程间抛出随机的 Realm 管理的对象,特别是如果你使用的 RxJava 已经有 observeOn(AndroidSchedulers.mainThread()) 几乎做同样的事情跨度>
  • P.S.您正在打开一个永远不会关闭的新 Realm 实例
  • 为了回答这个问题,需要知道你对从 Realm 获得的RealmResults&lt;T&gt; 做了什么
  • i just want to create a realm instance on my background thread and pass it to the main thread to create a realm query 你不能在线程之间传递 Realm 实例。它在文档中。
  • 我更新了我的问题并添加了 DBService 方法的实现。我还没有关闭那个领域实例吗?

标签: java android multithreading realm


【解决方案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());

【讨论】:

  • 此代码无法编译。 queryFactory.create(realm).asObservable() create(realm) 没有 asObservable as 方法
  • 应该是我的例子所示的结果
  • 是的,我想通了。我正在尝试它并且它有效。但我面临一个性能问题。它冻结了我的 UIThread,但我仍在检查它是否有别的东西
  • 我认为它是别的东西。除非你的 GC 运行不正常
  • 出于好奇,这是在什么调度程序上?
猜你喜欢
  • 2012-01-08
  • 2012-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-30
  • 1970-01-01
相关资源
最近更新 更多