App使用RxJava进行网络调用,然后使用数据库中的数据修改结果并显示它们。 App使用android.database.ContentObserver监听数据库更改,并在有更改时修改数据。目前它与下面的代码一起工作,但有一些更好的RX方式如何实现相同? 谢谢!
Observable<ArrayList<Foo>> observable = Observable.create(new Observable.OnSubscribe<ArrayList<Foo>>() {
@Override
public void call(Subscriber<? super ArrayList<Foo>> subscriber) {
//make api call and get list of foos
ArrayList<Foo> apiResults = api.getFooList();
//loop results and if foo is already in local sqlite db, update it with local values
for (Foo foo : apiResults) {
if(localSqlite.contains(foo){
foo.update(localSqlite.get(foo));
}
}
subscriber.onNext(apiResults);
HandlerThread observerThread = new HandlerThread("ContentObserver-thread");
observerThread.start();
final ContentObserver co = new ContentObserver(new Handler(observerThread.getLooper())) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
for (Foo foo : apiResults) {
if(localSqlite.contains(foo){
foo.update(localSqlite.get(foo));
}
subscriber.onNext(apiResults);
}
mContext.getContentResolver().registerContentObserver(uri, true, co);
subscriber.add(Subscriptions.create(new Action0() {
@Override
public void call() {
mContext.getContentResolver().unregisterContentObserver(co);
}
}));
}
Subscription subscription = observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
答案 0 :(得分:0)
框的调查SqlBrite的建议可能是最好的做法,但如果你没有时间学习新的API,我发现这是一种很酷的技术。
如果将每个数据库查询结果包装在行为主题中,则可以使用其URI作为键将其缓存在哈希映射中。然后,当您覆盖Content Observer的onChange方法时,您可以轻松地将刷新的对象推送到下游:
final protected MaxSizeHashMap<Uri, Subject<T, T>> subjectMap = new MaxSizeHashMap<>(cacheSize / 300);
final private ContentObserver contentObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (subjectMap.containsKey(uri)) {
subjectMap.get(uri).onNext(query(uri));
}
}
};
然后在你的get方法中,构建对象,将其包装在行为主题中并在返回observable之前将其添加到地图中:
public Observable<T> getFoo(U id) {
Uri uri = getUriForId(id);
if (!subjectMap.containsKey(uri)) {
subjectMap.put(uri, BehaviorSubject.create(query(id)));
}
return subjectMap.get(uri);
}