2017-01-20 10 views
2

バックグラウンドスレッドの実装を、私がsubscribeOn(AndroidScheduler.from(/ backgroundThreadWithLooper /)に渡すことができるLooperで共有できますか?ルーパーを使ってバックグラウンドスレッドを作成するには

ライブオブジェクトの更新を取得しながら、すべての操作をバックグラウンドで実行するDBServiceクラスを実装しようとしているため、これが必要です。私はのaddChangeListenerを適用するときに、例外がスローされます。

java.lang.IllegalStateException: Your Realm is opened from a thread without a Looper. Async queries need a Handler to send results of your query 

または私はfindAllのを(使用する場合)の代わりにfindAllAsync()の:

java.lang.IllegalStateException: You can't register a listener from a non-Looper thread or IntentService thread. 

DBServiceコード:

public Observable<List> getAll(Class clazz) { 
    return Observable.defer(() -> { 
     Realm realm = Realm.getDefaultInstance(); 
     return realm.where(clazz).findAll().asObservable() 
       .map(o -> realm.copyFromRealm((RealmResults) o)) 
       .doOnUnsubscribe(() -> closeRealm(realm)) 
       .doOnTerminate(() -> closeRealm(realm)); 
    }); 
} 
+0

私のために働いた 'HandlerThread' – pskink

+0

@pskinkのおかげで、見 –

答えて

2

HandlerThreadが仕事をします。

HandlerThread handlerThread = new HandlerThread("backgroundThread"); 
if (!handlerThread.isAlive()) 
    handlerThread.start(); 
AndroidSchedulers.from(handlerThread.getLooper()) 
0

このルーパー付きスレッドの例です。

public class GameLoop extends Thread { 

@Override 
public void run() { 
    super.run(); 
    Looper.prepare(); // at first write this line of code 
    //do something 
    Looper.loop(); //and at the end write this line 
} 

}

0

これは

01-21 00:58:51.672 2094-2127/com.zhuinden.rxrealm I/DogView: Realm write successful [1] :: [Munch]. 
01-21 00:58:51.672 2094-2115/com.zhuinden.rxrealm I/REALM SUBSCRIPTION: An event occurred on background thread! 

で私

public class MainScopeListener 
     extends Fragment { 
    Realm realm; 

    HandlerThread handlerThread; 

    Scheduler looperScheduler; 

    Observable<Realm> realmObservable; 

    Subscription realmSubscription; 

    Handler handler = new Handler(Looper.getMainLooper()); 

    public MainScopeListener() { 
     setRetainInstance(true); 
     realm = Realm.getDefaultInstance(); 
     Injector.INSTANCE.initializeComponent(realm); 
     handlerThread = new HandlerThread("REALM_LOOPER") { 
      @Override 
      protected void onLooperPrepared() { 
       super.onLooperPrepared(); 
       Log.i(getName(), "ON LOOPER PREPARED"); 
       handler.post(() -> { 
        looperScheduler = AndroidSchedulers.from(handlerThread.getLooper()); 
        realmObservable = Observable.create(new Observable.OnSubscribe<Realm>() { 
         @Override 
         public void call(Subscriber<? super Realm> subscriber) { 
          final Realm observableRealm = Realm.getDefaultInstance(); 
          observableRealm.setAutoRefresh(true); 
          final RealmChangeListener<Realm> listener = realm1 -> { 
           if (!subscriber.isUnsubscribed()) { 
            subscriber.onNext(observableRealm); 
           } 
          }; 
          subscriber.add(Subscriptions.create(() -> { 
           observableRealm.removeChangeListener(listener); 
           observableRealm.setAutoRefresh(false); 
           observableRealm.close(); 
          })); 
          observableRealm.addChangeListener(listener); 

          // Immediately call onNext with the current value, as due to Realm's auto-update, it will be the latest 
          // value. 
          subscriber.onNext(observableRealm); 
         } 
        }); 
        realmSubscription = realmObservable.unsubscribeOn(looperScheduler).subscribeOn(looperScheduler).subscribe(realm12 -> { 
         Log.i("REALM SUBSCRIPTION", "An event occurred on background thread!"); 
        }); 
       }); 
      } 
     }; 
     handlerThread.start(); 
    } 

    public void configureRealmHolder(MainActivity.RealmHolder realmHolder) { 
     realmHolder.realm = this.realm; 
    } 

    @Override 
    public void onDestroy() { 
     if(realmSubscription != null && !realmSubscription.isUnsubscribed()) { 
      realmSubscription.unsubscribe(); 
     } 
     handlerThread.quit(); 
     realm.close(); 
     super.onDestroy(); 
    } 
} 

@SuppressWarnings("NewApi") 
private Subscription writePeriodic() { 
    return Observable.interval(2000, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) // 
      .takeWhile(aLong -> counter < DogNames.values().length) // 
      .observeOn(Schedulers.io()) 
      .doOnNext(aLong -> { 
       try(Realm bgRealm = Realm.getDefaultInstance()) { 
        bgRealm.executeTransaction(realm1 -> { 
         long currentIndex = realm1.where(Dog.class).max(Dog.Fields.ID.getField()).longValue(); 
         Dog dog = new Dog(); 
         dog.setId(currentIndex + 1); 
         dog.setName(DogNames.values()[((Long) dog.getId()).intValue() % DogNames.values().length].name()); 
         dog = realm1.copyToRealmOrUpdate(dog); 
         Log.i(TAG, "Realm write successful [" + counter + "] :: [" + dog.getName() + "]."); 
         counter++; 
        }); 
       } 
      }).subscribe(); 
} 

結果のために働いているように見えるので、HandlerThreadレルムは、自動更新を受信することができます。

レルムからコピーすると、結果が熱心に評価されるため、大きなデータセットを効率的に処理する方法ではありません。

+0

私はあなたのアプローチを好むが、それでもこれは、レルムのインスタンスを閉じるときの私の問題を解決しません。私は、アクティビティライフサイクルにさらされていないクラスで私のDB操作を行っています。ですから、私はすべての操作でインスタンスを開いたり閉じたりして、copyFromRealmを使用させます。私はこのパターンを維持したいが、私もライブアップデートをしたい。私はコードで質問を更新します。 –

関連する問題