使用RxJava從多個資料來源擷取資料

來源:互聯網
上載者:User

使用RxJava從多個資料來源擷取資料

  

試想,需要一些動態資料的時候,只要每次都請求網路就可以了。但是,更有效率的做法是,把連網得到的資料,緩衝到磁碟或記憶體。

具體的說,計劃如下:

我將通過使用 RxJava ,來實現這個計劃。

基本模式

為每一個資料來源網路,磁碟和記憶體)建立Observable,使用concat()和first()操作符,構造一個簡單的實現方式。

concat() 操作符持有多個Observable對象,並將它們按順序串聯成隊列。 first() 操作符只從串聯隊列中取出並發送第一個事件。因此,如果使用concat().first(),無論多少個資料來源,只有第一個事件會被檢索出並發送。

 
  1. // Our sources (left as an exercise for the reader) 
  2. Observable memory = ...;  
  3. Observable disk = ...;  
  4. Observable network = ...; 
  5.  
  6. // Retrieve the first source with data 
  7. Observable source = Observable  
  8.   .concat(memory, disk, network) 
  9.   .first(); 
  10.  
  11. // Our sources (left as an exercise for the reader) 
  12. Observablememory = ...;   
  13. Observabledisk = ...;   
  14. Observablenetwork = ...; 
  15.  
  16. // Retrieve the first source with data 
  17. Observablesource = Observable   
  18.   .concat(memory, disk, network) 
  19.   .first(); 

這種模式的關鍵在於concat()操作符只有需要資料的時候才會訂閱所有的Observable資料來源。由於first()操作符會較早的停止檢 索隊列,所以,如果存在快取資料,就沒有必要訪問較慢的資料來源。 也就是說,如果memory返回結果,就不必擔心disk和network會被訪問。相反地,如果記憶體和磁碟都沒有資料,才執行網路請求。

注意concat()所持有的Observable資料來源,是按照一個接一個的順序被檢索的。

持久化資料

很明顯,下一步是快取資料。如果不把網路請求後的結果緩衝到磁碟,磁碟訪問後的結果緩衝到記憶體,那麼這根本不就不叫緩衝。接下來要寫的代碼就是,網路資料的持久化操作。

我的解決方案是,讓每個資料來源在發送完事件後,都儲存或者快取資料。

 
  1. Observable networkWithSave = network.doOnNext(new Action1() { 
  2. @Override public void call(Data data) { 
  3. saveToDisk(data); 
  4. cacheInMemory(data); 
  5. }); 
  6.  
  7. Observable diskWithCache = disk.doOnNext(new Action1() { 
  8. @Override public void call(Data data) { 
  9.   cacheInMemory(data); 
  10. }); 
  11.  
  12.  ObservablenetworkWithSave = network.doOnNext(new Action1() { 
  13. @Overridepublic void call(Datadata) { 
  14. saveToDisk(data); 
  15. cacheInMemory(data); 
  16. }); 
  17.  
  18. ObservablediskWithCache = disk.doOnNext(new Action1() { 
  19. @Overridepublic void call(Datadata) { 
  20.   cacheInMemory(data); 
  21. }); 

現在,如果你使用networkWithSave和diskWithCache,資料將會在載入後自動儲存。

這個策略的另一個優勢在於networkWithSave和diskWithCache可以在任何地方被使用,不局限於我們的多資料模式下。)

陳舊的資料

不幸的,現在我們儲存資料的那些代碼,執行的有點過頭了。無論資料是否過時,它總是返回相同的資料。我們希望做到,偶爾串連伺服器抓取最新的資料。

解決方案在於,使用first()操作符進行過濾。就是設定它拒絕接收毫無價值的資料。

 
  1. Observable source = Observable 
  2.     .concat(memory, diskWithCache, networkWithSave) 
  3.     .first(new Func1() { 
  4.       @Override public Boolean call(Data data) { 
  5.         return data.isUpToDate(); 
  6.       } 
  7.     }); 
  8.  
  9. Observablesource = Observable 
  10.     .concat(memory, diskWithCache, networkWithSave) 
  11.     .first(new Func1() { 
  12.       @Overridepublic Boolean call(Datadata) { 
  13.         return data.isUpToDate(); 
  14.       } 
  15.     }); 

現在,我們只需要發送被斷定為最新資料的事件就OK了。因此,只要有一個資料來源的資料到期,就繼續檢索下一個資料來源,直到找到最新資料為止。

first()和takeFirst()操作符的比較

對於這種設計模式,first()和takeFirst()操作符可以二選其一。

兩種調用方式的區別在於,如果所有資料來源的資料均到期,沒有任何的有效資料作為事件發送,first()會拋出 NoSuchElementException異常譯者註:first()操作符均return false),而takeFirst()操作符則直接調用完成操作,不會拋出任何異常。

使用哪個操作符,完全取決於是否需要明確處理缺失的資料。

程式碼範例

可以從這裡檢出,以上所有代碼的實現樣本: https://github.com/dlew/rxjava-multiple-sources-sample 。

如果需要一個真實樣本,檢出 Gfycat App ,它在擷取資料的時候使用了這種模式。項目並沒有使用以上展示的所有功能因為不需要),但是,示範了concat().first()的基本用法。


 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.