有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用copyFromRealm发送副本时,从错误线程访问java领域异常

当流式传输领域对象的副本而不是领域引用并在调度程序上观察它时。IO线程时,出现了著名的异常消息“来自错误线程的领域访问。领域对象只能在创建它们的线程中访问”的崩溃

副本不应该是无线程的吗?我可以从一个线程生成它并在另一个线程上处理它吗

这就是我如何创造可观察的

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

以下是我如何观察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();
                }
            });

共 (2) 个答案

  1. # 1 楼答案

    您在schedulers.io上订阅,同时使用UI线程中的领域实例:

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

    您想要的是一种跨线程移动查询的简单方法,这里的工作仍在进行中:https://github.com/realm/realm-java/pull/1978。在此之前,您可以通过以下方式解决此问题:

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

    请注意,RealmChangeListeners只在循环线程上工作,这意味着您可能需要将工作线程更改为H

    HandlerThread bgThread = new HandlerThread("workerThread");
    Handler handler = new Handler(bgThread.getLooper());
    
    getAllBrands(realm).subscribeOn(HandlerScheduler.from(handler));
    
  2. # 2 楼答案

    问题

    Can I produce it from one thread and process it on a different thread?

    答案是否定的。您可以在here中阅读领域的描述

    Although Realm files can be accessed by multiple threads concurrently, you cannot hand over Realms, Realm objects, queries, and results between threads. The thread example shows how to use Realm in a multithreading environment.