我希望将Observable
封装在一个查询ContentProvider
的逻辑中,并订阅ContentProvider
光标以提供持续更新。
由于observable做IO工作,我需要在Schedulers.io()
订阅它。问题是我不能注册ContentObserver
,因为它需要一个looper准备好的线程。
在单个Observable
中管理该内容并封装的建议方法是什么。
代码说明:
public Observable<Integer> unreadCountObservable() {
return Observable.create(subscriber -> {
new UnreadCountObservable(subscriber);
});
}
private class UnreadCountObservable {
private Subscriber subscriber;
public UnreadCountObservable(Subscriber subscriber) {
this.subscriber = subscriber;
Cursor cursor = queryUnread(subscriber);
cursor.registerContentObserver(observer);
subscriber.add(Subscriptions.create(() -> {
cursor.unregisterContentObserver(observer);
cursor.close();
}));
}
@NonNull
private Cursor queryUnread(Subscriber subscriber) {
Cursor cursor = contextProvider.getContext().getContentResolver().query(Uri.parse(CONTENT_URI),SMS_PROJECTION,SMS_SELECTION_UNREAD,SMS_PROJECTION,null);
if(cursor.moveToNext()) {
Integer count = cursor.getInt(0);
subscriber.onNext(count);
} else {
subscriber.onNext(0);
}
return cursor;
}
private ContentObserver observer = new ContentObserver(new Handler()) {
@Override
public boolean deliverSelfNotifications() {
return false;
}
@Override
public void onChange(boolean selfChange) {
Timber.d("New sms data changed");
queryUnread(subscriber);
}
};
}
注1 上述代码的问题在于,由于registerObserver无法使用.subscribeOn(Schedulers.io()
调用,如果将其称为mainThread,则查询也会在其上运行)
注意:将所有内容封装在一个Observable
中是关键要求和此问题的动机
我现在最好的想法是为我使用Observable的活动创建一个HandlerThread并使用该线程中的looper。但是想知道是否有更好的替代方案,并且如果制作一个通用调度程序(例如looperIoScheduler())有意义就会导致问题。
答案 0 :(得分:1)
在Observable
链中,您可以根据需要随时更改帖子。看看here。
函数rx.Observable#observeOn(rx.Scheduler)
可以位于链中的任何位置。尝试做这样的事情(伪代码):
Observable.just(cursor)
.observeOn(AndroidSchedulers.mainThread())
.map((Cursor) -> {
cursor.registerContentObserver(observer);
return cursor;
}
}).observeOn(Schedulers.io());
subscriber.add(Subscriptions.create(() -> {
cursor.unregisterContentObserver(observer);
cursor.close();
}));
答案 1 :(得分:-1)
好的,为什么要赢得这项工作呢?
public Observable<Integer> unreadCountObservable() {
return Observable.defer(() -> Observable.create(subscriber -> {
new UnreadCountObservable(subscriber);
}))
.subscribeOn(Schedulers.io());
}