带有自动更新的领域,copyFromRealm和RxJava

时间:2018-08-19 03:25:35

标签: android android-recyclerview realm rx-java2

我正在使用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线程吗?我该怎么办?

2 个答案:

答案 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;
    }

}