我正在使用Realm的rFlow绑定到Flowable,以便在项目更新时得到通知。我必须在UI线程中执行此操作才能从领域获取更新通知。另一方面,我需要使结果不受管理,以便在线程之间传递结果,并避免不一致。
public Flowable<List<City>> getLiveCityList() {
return mRealm.where(City.class)
.findAll()
.asFlowable()
.map(mRealm::copyFromRealm)
.subscribeOn(AndroidSchedulers.mainThread());
}
例如,我使用diffUtils更新recyclerview的项目,并且需要获取两个不同的列表(不同的参考)。我也必须在UI线程中执行copyFromRealm,因为RealmResults仅应在创建它们的线程中使用。
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtilCallback(mItems, newItems), true);
mItems = newItems;
diffResult.dispatchUpdatesTo(BaseRecyclerViewAdapter.this);
我应该将所有这些移出UI线程吗?我该怎么办?
答案 0 :(得分:1)
首先,您需要创建一个HandlerThread并用AndroidSchedulers对其进行包装,以将其与Rx作为调度程序一起使用:
SchedulerHolder looperScheduler = new SchedulerHolder(); // holds scheduler instance
handlerThread = new HandlerThread("LOOPER_SCHEDULER");
handlerThread.start();
synchronized(handlerThread) {
looperScheduler.setScheduler(AndroidSchedulers.from(handlerThread.getLooper()));
}
然后,您现在可以将其用作subscribeOn().unsubscribeOn()
,用于在后台线程上运行的RealmQuery:
private interface QuerySelector<E extends RealmModel> {
RealmResults<E> createQuery(Realm realm);
}
private <T extends RealmModel> Observable<List<T>> createResults(QuerySelector<T> querySelector) {
return Observable.create((ObservableOnSubscribe<List<T>>) emitter -> {
Realm realm = Realm.getDefaultInstance(); // can use custom config too
final RealmResults<T> results = querySelector.createQuery(realm);
final RealmChangeListener<RealmResults<T>> realmChangeListener = element -> {
if(element.isLoaded() && !emitter.isDisposed()) {
List<R> list = new ArrayList<>(element.size());
Collections.addAll(list, realm.copyFromRealm(element));
if(!emitter.isDisposed()) {
emitter.onNext(list);
}
}
};
emitter.setDisposable(Disposables.fromAction(() -> {
if(results.isValid()) {
results.removeChangeListener(realmChangeListener);
}
realm.close();
}));
results.addChangeListener(realmChangeListener);
if(results.isLoaded()) {
emitter.onNext(realm.copyFromRealm(results));
}
})
.subscribeOn(looperScheduler.getScheduler())
.unsubscribeOn(looperScheduler.getScheduler());
}
然后您可以使用
进行调用public Observable<List<City>> getCities() {
return createResults((realm) -> realm.where(City.class).findAllAsync());
}
别忘了在某个时候说observeOn(AndroidSchedulers.mainThread())
。
答案 1 :(得分:1)
@EpicPandaForce https://stackoverflow.com/a/51916307/2425851的修改后的答案 用法:
public override fun onCreate(savedInstanceState: Bundle?) {
//...
mRealmStore.changeListenerObservable<City>{Realm.getInstance(builder.build())}
.observeOn(AndroidSchedulers.mainThread())
.subscribe{list->/*do smth in UI*/}
}
RealmStore.kt
class RealmStore{
inline fun <reified T : RealmObject> changeObservable(crossinline getRealm: () -> Realm): Observable<MutableList<T>> {
return Observable.create<MutableList<T>> { emitter ->
val realm = getRealm()
val listener = RealmChangeListener<RealmResults<T>> { realmResults ->
val mutableList: MutableList<T> = realm.copyFromRealm(realmResults)
emitter.onNext(mutableList)
}
val realmResults = realm
.where(T::class.java)
.findAllAsync()
realmResults.addChangeListener(listener)
emitter.setDisposable(Disposables.fromAction {
realmResults.removeChangeListener(listener)
})
}
.subscribeOn(RealmScheduler.background())
.unsubscribeOn(RealmScheduler.background())
.observeOn(Schedulers.io())
}
}
RealmScheduler.java
public class RealmScheduler {
private Scheduler scheduler;
private static RealmScheduler instance;
static RealmScheduler getInstance() {
RealmScheduler localInstance = instance;
if (localInstance == null) {
synchronized (RealmScheduler.class) {
localInstance = instance;
if (localInstance == null) {
instance = localInstance = new RealmScheduler();
}
}
}
return localInstance;
}
private RealmScheduler() {
HandlerThread handlerThread = new HandlerThread("REALM_SCHEDULER");
handlerThread.start();
scheduler = AndroidSchedulers.from(handlerThread.getLooper());
}
public static Scheduler background() {
Scheduler scheduler = getInstance().getScheduler();
if (scheduler == null) {
throw new NullPointerException("realm scheduler == null");
}
return scheduler;
}
private Scheduler getScheduler() {
return scheduler;
}
}