2016-03-07 6 views
5

レルム参照の代わりにレルムオブジェクトのコピーをストリーミングし、Schedulers.IOスレッドで観察すると、有名な例外メッセージ "Realm access from incorrect thread Realmオブジェクトは作成されたスレッドでのみアクセスできます。不正なスレッドからのレルムアクセスcopyFromRealmを使用してコピーが送信されたときの例外

スレッドは空きであってはいけませんか?あるスレッドからそれを生成し、それを別のスレッドで処理することはできますか?

これは、私が観測可能にする方法です。

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(); 
       } 
      }); 
+1

にあなたのワーカースレッドを変更する必要があることを意味しているルーパースレッド上で動作していること

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

注:それまでは、あなたはこのようにそれを自分で行うことによって、それを回避することができますあなたが使っている 'realm'は' io() 'スケジューラーにありません。 – EpicPandaForce

答えて

0

QUESTION

は、私は1つのスレッドからそれを生成し、別のスレッドでそれを処理することはできますか?

回答はNOです。レルムのファイルが同時に複数のスレッドによってアクセスすることができますが、あなたはレルム、レルムのオブジェクト、クエリ、スレッド間の結果を引き渡すことができない、here

レルムの説明を読むことができます。スレッドの例は、マルチスレッド環境でRealmを使用する方法を示しています。

+2

しかし、問題はRealmインスタンスに関連付けられていないと思われる 'copyFromRealm()'を使って、分離されたオブジェクトについてです。 – EpicPandaForce

7

UIスレッドからレルムインスタンスを使用しているときは、schedulers.ioに加入している:

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。レルムChangeListenersにのみ、あなたはおそらくH

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

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

私はスレッド間でクエリを移動しようとしていません。代わりに、私は分離Realmオブジェクトのコピーをストリーミングしようとしています。それを作成した領域インスタントに関係なく、複数のスレッドにわたってデタッチされたデータを使用することはできませんか? – sam33r

+0

'map(brand - > realm.copyFromRealm(brand));'ブランドはUIスレッドで作成され、 'schedulers.io()'スレッドでアクセスされるオブジェクトです。私の解決策は、そのための回避策です( 'schedulers.io()'スレッドでクエリを実行することによって) –

+0

今、 "あなたは非ルーパースレッドからリスナーを登録できません"というメッセージが表示されます。 – sam33r

関連する問題