不正确的线程异常境界访问,同时副本使用copyFromRealm发 [英] Realm access from incorrect thread Exception while a copy was sent using copyFromRealm

查看:3897
本文介绍了不正确的线程异常境界访问,同时副本使用copyFromRealm发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在流媒体领域的模仿对象,而不是境界参考,并观察它Schedulers.IO线程,则与著名的异常消息不正确的线程访问境​​界崩溃。境界对象只能在创建它们的线程访问。

不应在副本线程免费的吗?我能生产从一个线程和处理它在不同的线程?

这是我如何创建观测。

 公众观测和LT;品牌> getAllBrands(){
    返回realm.where(Brand.class)
            .findAll()
            .asObservable()
            .flatMap(可观察::从)
            .MAP(品牌 - > realm.copyFromRealm(品牌));
}

以下是我如何观察getAllBrands()。

 观测与LT;品牌> brandObservable = dataManager.getAllBrands();    brandObservable.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(新观察<品牌>(){
                @覆盖
                公共无效onCompleted(){
                    Log.d(反应,已完成);
                }                @覆盖
                公共无效onerror的(Throwable的E){
                    Log.d(反应,e.getMessage());
                }                @覆盖
                公共无效onNext(品牌品牌){
                    dataSource.add(brand.getName());
                    myAdapter.notifyDataSetChanged();
                }
            });


解决方案

您是在 schedulers.io 订阅,而使用从UI线程的领域实例:

  realm.where(Brand.class)
        .findAll()
        .asObservable()
        .flatMap(可观察::从)
        .MAP(品牌 - > realm.copyFromRealm(品牌))//错线程领域实例
        .subscribeOn(schedulers.io());

什么是你的是后移动跨线程的查询,仍然工作在这里正在进行一个简单的方法:的 https://github.com/realm/realm-java/pull/1978 。在那之前,你可以解决它自己做这样的:

 公众观测和LT;品牌> getAllBrands(最终境界境界){
    返回Observable.create(新Observable.OnSubscribe<名单,LT;品牌>>(){
        @覆盖
        公共无效电话(最终用户和LT ;?超级列表与LT;品牌>>用户){
            境界obsRealm = Realm.getInstance(realm.getConfiguration());
            最后RealmResults<品牌>结果= obsRealm.where(Brand.class).findAll();
            最后RealmChangeListener监听器=新RealmChangeListener(){
                @覆盖
                公共无效的onChange(){
                    subscriber.onNext(realm.copyFromRealm(结果));
                }
            };
            results.addChangeListener(监听);
            subscriber.add(Subscriptions.create(新Action0(){
                @覆盖
                公共无效调用(){
                    realm.removeChangeListener(监听);
                    realm.close();
                }
            }));        }
    })
    .flatMap(可观察::从);
}

请注意该领域Changelisteners只在环线的工作,这意味着你可能需要您的工作线程切换到A h对

  HandlerThread bgThread =新HandlerThread(的WorkerThread);
处理程序处理程序=新的处理程序(bgThread.getLooper());getAllBrands(境界).subscribeOn(HandlerScheduler.from(处理));

When streaming copy of realm objects instead of realm reference and observing it on Schedulers.IO thread, there is a crash with the famous exception message "Realm access from incorrect thread. Realm objects can only be accessed in the thread they were created."

Shouldn't the copy be thread free? Can I produce it from one thread and process it on a different thread?

This is how I am creating observable.

 public Observable<Brand> getAllBrands() {
    return realm.where(Brand.class)
            .findAll()
            .asObservable()
            .flatMap(Observable::from)
            .map(brand -> realm.copyFromRealm(brand));
}

Following is how I observe getAllBrands().

 Observable<Brand> brandObservable = dataManager.getAllBrands();

    brandObservable.observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io())
            .subscribe(new Observer<Brand>() {
                @Override
                public void onCompleted() {
                    Log.d("reactive", "completed");
                }

                @Override
                public void onError(Throwable e) {
                    Log.d("reactive", e.getMessage());
                }

                @Override
                public void onNext(Brand brand) {
                    dataSource.add(brand.getName());
                    myAdapter.notifyDataSetChanged();
                }
            });

解决方案

You are subscribing on schedulers.io while using the Realm instance from the UI thread:

realm.where(Brand.class)
        .findAll()
        .asObservable()
        .flatMap(Observable::from)
        .map(brand -> realm.copyFromRealm(brand)) // realm instance on the wrong thread
        .subscribeOn(schedulers.io());            

What are you after is an easy way to move a query across threads, which is still work-in-progress here: https://github.com/realm/realm-java/pull/1978. Until then you can work around it by doing it yourself like this:

public Observable<Brand> getAllBrands(final Realm realm) {
    return Observable.create(new Observable.OnSubscribe<List<Brand>>() {
        @Override
        public void call(final Subscriber<? super List<Brand>> subscriber) {
            Realm obsRealm = Realm.getInstance(realm.getConfiguration());
            final RealmResults<Brand> results = obsRealm.where(Brand.class).findAll();
            final RealmChangeListener listener = new RealmChangeListener() {
                @Override
                public void onChange() {
                    subscriber.onNext(realm.copyFromRealm(results));
                }
            };
            results.addChangeListener(listener);
            subscriber.add(Subscriptions.create(new Action0() {
                @Override
                public void call() {
                    realm.removeChangeListener(listener);
                    realm.close();
                }
            }));

        }
    })
    .flatMap(Observable::from);
}

Note that Realm Changelisteners only work on Looper threads which means you probably need to change your worker thread to a H

HandlerThread bgThread = new HandlerThread("workerThread");
Handler handler = new Handler(bgThread.getLooper());

getAllBrands(realm).subscribeOn(HandlerScheduler.from(handler));

这篇关于不正确的线程异常境界访问,同时副本使用copyFromRealm发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆