繁体   English   中英

RxJava 使用 observables 为 android 构建缓存

[英]RxJava building cache with observables for android

我很难理解如何使用 RxJava 构建缓存。 这个想法是我需要从内存缓存中获取数据或从我的数据库 (dynamoDb) 加载。 但是,这个缓存应该在片段和/或线程之间共享。 因此,我需要返回当前正在运行但尚未完成的现有 observable。 这允许线程赶上而不是做不必要的工作。 我是 RxJava 的新手,所以这就是我想到的草图(为简洁起见,缺少一些代码):

public class DBCache<K, T> {
private final ConcurrentHashMap<K, Set<T>> resultCache = new ConcurrentHashMap<>;
private final ConcurrentHashMap<K, Observable<Set<T>>> observableCache = new ConcurrentHashMap<>;

private Observable<Set<T>> getFromCache(final DynamoDbCacheKey<K, T> query) {
    return Observable.create(new Observable.OnSubscribe<Set<T>>() {
        @Override
        public void call(Subscriber<? super Set<T>> subscriber) {
        Set<T> results = resultCache.get(query.getKey());
        if (results != null && results.size() > 0) {
            subscriber.onNext(results);
        }
        subscriber.onCompleted();
        }
    });
}

public Observable<Set<T>> get(final QueryCacheKey<K, T> query){
    Observable<Set<T>> cachedObservable = observableCache.get(query.getKey());
    if (cachedObservable != null) {
        return cachedObservable;
    }
    Observable<Set<T>> observable = Observable
        .concat(getFromCache(query), getFromNetwork(query))
        .first()
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .cache();
    observableCache.putIfAbsent(query.getKey(), observable);
return observable;
} 

private Observable<Set<T>> getFromNetwork(final QueryCacheKey<K, T> query) {
    return Observable.create(new Observable.OnSubscribe<Set<T>>() {
    @Override
    public void call(Subscriber<? super Set<T>> subscriber) {
        try {
            Set<T> results = loadFromDb(query); //omitted
            resultCache.putIfAbsent(query.getKey(), results);
            subscriber.onNext(results);
            subscriber.onCompleted();
            observableCache.remove(query.getKey());
        } catch (Exception exception) {
            subscriber.onError(exception);
        }
    }
    });
} 

}

有没有更好的方法通过 RxJava 实现这一点(对缓存策略不感兴趣)。 有什么想法吗?

下面是一个简单的缓存和检索值的例子:

public class RxCache<K, V> {

    final ConcurrentHashMap<K, AsyncSubject<V>> cache;

    final Func1<K, Observable<V>> valueGenerator;

    public RxCache(Func1<K, Observable<V>> valueGenerator) {
        this.valueGenerator = valueGenerator;
        this.cache = new ConcurrentHashMap<>();
    }

    public Observable<V> get(K key) {
        AsyncSubject<V> o = cache.get(key);
        if (o != null) {
            return o;
        }

        o = AsyncSubject.create();

        AsyncSubject<V> p = cache.putIfAbsent(key, o);
        if (p != null) {
            return p;
        }

        valueGenerator.call(key).subscribe(o);

        return o;
    }

    public void remove(K key) {
        cache.remove(key);
    }
}

如果您有多个值,请将AsyncSubject替换为ReplaySubject

您可以使用BehaviorSubject应用缓存,创建一个Observable ,然后将其转换为BehaviorSubject ,然后订阅此Subject以获取您的数据。

现在这个Subject将作为一个Observable做出反应,当订阅它时,它会给你获取的最新数据,并在更新时发出新数据。

在此处查看更多详细信息和实施: https : //medium.com/@jaerencoathup/repository-pattern-using-rxjava-and-room-4ce79e4ffc5c

另一种方法: https : //medium.com/@elye.project/rxjava-clean-way-of-prefetching-data-and-use-later-54800f2652d4

通过简单示例了解更多关于 Subjects: https : //blog.mindorks.com/understanding-rxjava-subject-publish-replay-behavior-and-async-subject-224d663d452f

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM