rxjava和android.database.contentobserver

时间:2015-10-27 10:49:51

标签: android rx-java rx-android

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);

1 个答案:

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