【问题标题】:Realm, network operations, subscribing and observing on different threads with RxJava使用 RxJava 在不同线程上进行领域、网络操作、订阅和观察
【发布时间】:2016-04-20 10:51:43
【问题描述】:

我需要:

  • 在后台线程上从 API 获取一些数据
  • 在 UI 上显示数据
  • 保存到领域。

    fetchItemsFromServer().subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<ItemList>() {
        @Override
        public void call(ItemList items) {
    
            displayItems(items);
    
            try {
                realm.beginTransaction();
                realm.copyToRealmOrUpdate(itemList);
                realm.commitTransaction();
                Logger.v("Realm ", "Copied list object to realm");
            } catch (Exception e) {
                Logger.e("Realm Something went wrong ", e);
                realm.cancelTransaction();
            }
    
        }
    }
    

这会引发错误:从不正确的线程访问的领域

我有 4 个标签同时获取不同的消息。

fetchItemsFromServer() 是一个密集的调用,将这个调用限制在一个线程是不好的。我需要这种灵活性。

有没有人发现任何以这种方式使用领域的解决方法?

例如,大多数示例往往侧重于从 Realm 获取而不是使用网络操作:

下面的例子:

Rxjava - https://realm.io/news/realm-java-0.87.0/

在 RxJava 中使用领域 - https://realm.io/news/using-realm-with-rxjava/(以前的解决方案,但存在性能缺陷)

My Realm 由一个数据库模块通过依赖注入提供(Dagger 2)

@Module
public class DatabaseModule {

    public static final String REALM_FILE_NAME = "Realm name";

    @Provides
    Realm providesRealmInstance(Context context) {
    return Realm.getInstance(
            new RealmConfiguration.Builder(context)
                    .name(REALM_FILE_NAME)
                    .build());
    }
}

【问题讨论】:

  • 你从订阅者那里得到你的 Realm 实例?订阅者正在 UI 线程上进行保存,因此如果您的 Realm 实例也是在那里创建的,它应该可以工作。
  • @ChristianMelchior 我的领域是通过依赖注入注入的。一旦我删除了 API 调用的 subscribeOn(Schedulers.io()),一切正常。
  • 删除 subscribeOn(Schedulers.io()) 应该对您的订阅者没有影响,因为您 observeOn 是主线程。您的 fetchItemsFromServer() 是否以某种方式使用 Realm?
  • @ChristianMelchior 不,它调用一个请求,将项目返回为 Json,使用 Gson 解析为领域对象 ItemList
  • 那么我最好的想法是 Dagger 以某种方式为您提供来自另一个线程的缓存版本。请注意,如果您按照示例配置您的 Realm,那么您可以通过在 Application 类中使用 setDefaultConfiguration 来避免使用 Dagger,并使用 Realm.getDefaultInstance() 创建实例。

标签: rx-java realm-list realm


【解决方案1】:

我不会在 UI 线程上保存数据,而是在后台使用以下模式:

fetchItemsFromServer()
    .doOnNext(new Action1<ItemList>() {
        @Override
        public ItemList call(ItemList list) {
            // Save data on the background thread
            Realm realm = Realm.getDefaultInstance();
            realm.beginTransaction();
            realm.copyToRealmOrUpdate(list);
            realm.commitTransaction();
            realm.close();
        }
    })
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Action1<ItemList>() {
    @Override
    public void call(ItemList items) {
        displayItems(items);
    }
}

【讨论】:

  • 这意味着您可能正在从其他地方获得异常。此代码 sn-p 保证仅在 1 个线程上使用 Realm 实例。
  • 我花了更多时间研究这个,你是对的。我从从 UI 访问领域的其他地方得到了异常。
猜你喜欢
  • 2015-06-04
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
  • 2018-06-11
  • 2022-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多