使用RxJava實現快取
在這篇文章中將使用reactiveX建立一個快取。RxJava / Kotlin沒有本機快取實現。因此,我必須使用RxJava和Kotlin為單個元素建立自己的快取(可擴充套件為Observable,Maybe等)。
主要思想是在一定時間內返回相同的元素。在那之後,我們將不得不從頭開始執行所有操作。
此快取有三個元件:SingleTransformer,SingleSource和Consumer。
消費者是一個簡單的回撥。它會接受我們想要的任何東西,因為它有一個void accept(T t)方法。當Observer執行onSuccess方法時執行此方法。
SingleSource是管道將訂閱的源。它有一個void subscribe(SingleObserver <T>observer)方法,其中SingleObserver只發出一個元素。當有人訂閱管道時執行此方法。
SingleTransformer對於組合單曲很有用。它有一個SingleSource<Downstream> apply(Single<Upstream> upstream) 方法,其中上游是傳入元素,下游是傳出元素。建立管道時將執行此方法。所以,它必須只執行一次。否則,將始終建立LastElementSeen,並且快取將不起作用。
首先,我們可以建立我們的消費者:
class LastElementSeen<T>(private val timeout: Long, private val unit: TimeUnit) : Consumer<T> { private var lastEmissionTimestamp: Long = 0 var value: T? = null override fun accept(latest: T) { lastEmissionTimestamp = DateTime.now().millis value = latest } // I used JodaTime: https://www.joda.org/joda-time/ for this piece of code. fun isValid(): Boolean { return value?.let { DateTime.now().minus(lastEmissionTimestamp).isBefore(unit.toMillis(timeout)) } ?: false } } |
該元素具有我們想要的任何物件,並且在接受時具有最後的發射時間戳。我們可以呼叫LastElementSeen,因為它只代表那個。此外,此物件還有責任是否仍然有效或已過期。
下一步是建立一個自定義SingleSource的實現來決定元素是否有效,我們必須發出相同的元素,否則我們必須再次訂閱。
class LastElementSeenSingle<T>(private var upstream: Single<T>, private val lastElementSeen: LastElementSeen<T>) : SingleSource<T> { override fun subscribe(observer: SingleObserver<in T>) { if (lastElementSeen.isValid()) { lastElementSeen.value?.let(observer::onSuccess) } else { upstream.subscribe(observer) } } } |
最後一步是建立我們的SingleTransformer:
class SingleRxCache<T>(private val timeout: Long, private val unit: TimeUnit) : SingleTransformer<T, T> { override fun apply(upstream: Single<T>): SingleSource<T> { val lastElementSeen = LastElementSeen<T>(timeout, unit) return LastElementSeenSingle(upstream.doOnSuccess(lastElementSeen), lastElementSeen) } } |
我們必須建立LastElementSeen和LastElementSeenSingle並使用upstream.doOnSuccess(lastElementSeen)方法從流中發出元素。
所以,現在我們有了反應式快取。我們來試試吧!快速測試:
@Test fun reactiveCacheTest() { val single = Single.create<Long> { emitter -> println("Creating single") emitter.onSuccess(counter++) }.map { println("Map") it }.compose(SingleRxCache<Long>(3, TimeUnit.SECONDS)) for (i in 1..5) { single.subscribe { value -> println(value) } Thread.sleep(1000) } } |
輸出:
Creating single Map 1 1 1 Creating single Map 2 2 |
在gist中看到完整的程式碼。
相關文章
- 使用RxJava快取Rest請求RxJava快取REST
- 使用ConcurrentHashMap實現快取HashMap快取
- SpringBoot中使用Redis實現快取Spring BootRedis快取
- WEB 應用快取解析以及使用 Redis 實現分散式快取Web快取Redis分散式
- 使用ThreadLocal來實現一個本地快取thread快取
- SpringBoot快取管理(二) 整合Redis快取實現Spring Boot快取Redis
- spring boot使用Jedis整合Redis實現快取(AOP)Spring BootRedis快取
- 快速入門:使用 .NET Aspire 元件實現快取元件快取
- 實現AVPlayer離線快取快取
- CefSharp自定義快取實現快取
- 快取 LRU 和 LFU 實現快取
- 使用Retrofit+RxJava實現網路請求RxJava
- 探討下如何更好的使用快取 —— Redis快取的特殊用法以及與本地快取一起構建多級快取的實現快取Redis
- 使用Go實現健壯的記憶體型快取Go記憶體快取
- 乾貨,使用布隆過濾器實現高效快取!過濾器快取
- SpringBoot中實現兩級快取Spring Boot快取
- LRU cache快取簡單實現快取
- 【SpringBoot】結合Redis實現快取Spring BootRedis快取
- Vue專案全域性配置頁面快取,實現按需讀取快取Vue快取
- 使用Retrofit+RxJava實現帶進度下載RxJava
- Laravel 實現二級快取 提高快取的命中率和細粒化快取 keyLaravel快取
- 手把手使用 PHP 實現 LRU 快取淘汰演算法PHP快取演算法
- 在Kubernetes上使用Spring Boot實現Hazelcast分散式快取 – PiotrSpring BootAST分散式快取
- MUI呼叫原生自定義方法實現計算快取與清空快取UI快取
- 利用localstorage實現本地訊息快取快取
- JavaScript隨機數實現防止快取JavaScript隨機快取
- Spring @cacheable註解實現的快取Spring快取
- MySQL與Redis實現二級快取MySqlRedis快取
- 15.SpringBoot整合Redis快取實現Spring BootRedis快取
- laravel利用Redis來實現網站快取讀取LaravelRedis網站快取
- 分分鐘使用Retrofit+Rxjava實現網路請求RxJava
- jetcache快取使用快取
- SpringBoot使用快取Spring Boot快取
- JS 實現快取演算法(FIFO/LRU)JS快取演算法
- 實現vue 的keep-alive快取功能VueKeep-Alive快取
- 借用workbox實現離線快取應用快取
- Retrofit和OkHttp實現 Android網路快取HTTPAndroid快取
- [記]SAF 中快取服務的實現快取