REST API에서 영화를 가져 오는이 FilmStore를 보유하고 있습니다.RxJava에서 HTTP 요청의 데이터 캐시
class CacheableFilmsStore(private val origin: FilmsStore) : FilmsStore {
private val cache = ReactiveCache<Film>()
override fun get(filmId: String): Observable<Film> {
return cache[filmId].onErrorResumeNext({
origin[filmId].doOnNext { film ->
cache.put(filmId, film)
}
})
}
}
을 그리고 난 메모리 내 데이터를 관리하는이 클래스 ReactiveCache 있습니다 :
class ReactiveCache<T> {
private val cache = LruCache<String, T>(4 * 1024 * 1024) //4MiB
operator fun get(key: String): Observable<T> {
return Observable.create { subscriber ->
//synchronized (this) { It doesn't work
val value = cache[key]
if (value == null) {
subscriber.onError(KeyNotExistsException())
} else {
subscriber.onNext(value)
subscriber.onCompleted()
}
//}
}
}
fun put(key: String, value: T) {
cache.put(key, value)
}
}
을
class ApiFilmsStore(private val tmdApi: TmdApi, private val converter: ApiFilmToFilmConverter) : FilmsStore {
override fun get(filmId: String): Observable<Film> {
return tmdApi.filmById(filmId).flatMap { apiFilm -> Observable.just(converter.convert(apiFilm)) }
.subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())
}
}
I이 존재하는 경우 캐시에서 데이터를 반환하는 장식이 또 다른 하나가
경쟁 조건이 발생하는 문제가 있습니다. 두 개의 프래그먼트는 앱이 시작될 때 동일한 영화를 가져오고, 두 번째 프래그먼트는 API에서 필름을 가져 오는 중입니다. 두 번째 프래그먼트가 영화를 가져올 때 아직 캐시에 저장되지 않았기 때문입니다.
어떻게 동기화 할 수 있습니까? synchronized
을 넣으려고했으나 작동하지 않습니다.
'ReactiveCache' 또는이를 사용하는 ApiFilmsStore가 싱글 톤 (아마도 DI 프레임 워크를 통해)으로 사용됩니까? 다른 말로하면, 그것은 같은 대상입니까? 즉, 두 개의 별도 캐시가있을 수 있다고 아직 배제 했습니까? – drhr
(또한, 사이드 노트 : 이것을 가지고있을 때 :'.flatMap {apiFilm -> Observable.just (converter.convert (apiFilm))}''.map {apiFilm -> converter.convert (apiFilm)}' 또는 w/lambda 메소드'.map (converter :: convert)') – drhr
응답 해 주셔서 감사합니다. 예, 두 조각 모두 동일한 인스턴스를 사용하고 있습니다. Dagger2와 함께 CacheableFilmsStore를 사용하고 있습니다. map, nice point로 flatMap을 변경했습니다.) –