当前位置: 首页 > 科技观察

使用RxJava从多个数据源获取数据

时间:2023-03-15 10:13:48 科技观察

试想一下,当你需要一些动态数据时,每次只需要请求网络即可。然而,更有效的方法是将从互联网上获取的数据缓存到磁盘或内存中。具体方案如下:偶尔的网络操作只是为了获取***数据。尽可能快地读取数据(通过获取以前缓存的网络数据)。我将使用RxJava来实现这个计划。基本模式为每个数据源(网络、磁盘和内存)创建一个Observable,使用concat()和first()运算符构建一个简单的实现。concat()运算符获取多个Observable对象并将它们按顺序连接到一个队列中。first()运算符仅接收并发出串联队列中的第一个事件。因此,如果使用concat().first(),无论有多少个数据源,都只会获取并发送第一个事件。//Oursources(leftasanexerciseforthereader)Observablememory=...;Observabledisk=...;Observablenetwork=...;//RetrievethefirstsourcewithdataObservablesource=Observable.concat(memory,disk,network).first();=...;Observabledisk=...;Observablenetwork=...;//RetrievethefirstsourcewithdataObservablesource=Observable.concat(memory,disk,network).first();这种模式的关键是concat()操作符只需要data才会订阅所有Observable数据源。由于first()运算符提前停止检索队列,如果有缓存数据,则无需访问较慢的数据源。也就是说,如果内存返回结果,就不用担心磁盘和网络被访问了。相反,只有在内存或磁盘中没有数据时才会执行网络请求。注意concat()持有的Observable数据源是被一个一个获取的。持久化数据显而易见的下一步是缓存数据。如果网络请求的结果不缓存到磁盘,而磁盘访问的结果缓存在内存中,那这根本就不叫缓存。接下来要写的代码是网络数据的持久化操作。我的解决方案是让每个数据源在发送事件后保存或缓存数据。ObservablenetworkWithSave=network.doOnNext(newAction1(){@Overridepublicvoidcall(Datadata){saveToDisk(data);cacheInMemory(data);}});ObservablediskWithCache=disk.doOnNext(newAction1(){@Overridepublicvoidcall(数据数据){cacheInMemory(数据);}});ObservablenetworkWithSave=network.doOnNext(newAction1(){@Overridepublicvoidcall(数据数据){saveToDisk(数据);cacheInMemory(数据);}});ObservablediskWithCache=disk.doOnNext(newAction1(){@Overridepublicvoidcall(Datadata){cacheInMemory(data);}});现在,如果您使用networkWithSave和diskWithCache,数据将在加载后自动保存。(这种策略的另一个优点是networkWithSave和diskWithCache可以在任何地方使用,不局限于我们的多数据模型。)陈旧数据不幸的是,我们目前保存数据的代码有点过度执行。无论数据是否过时,它总是返回相同的数据。我们希望这样做,偶尔连接服务器抓取***数据。解决方案是使用first()运算符进行过滤。只需将其设置为拒绝接受无价值的数据即可。Observablesource=Observable.concat(memory,diskWithCache,networkWithSave).first(newFunc1(){@OverridepublicBooleancall(Datadata){returndata.isUpToDate();}});Observablesource=Observable.concat(memory,diskWithCache,networkWithSave).first(newFunc1(){@OverridepublicBooleancall(Datadata){returndata.isUpToDate();}});现在,我们只需要发送判断为***data的事件就OK了。因此,只要一个数据源的数据过期,就继续取下一个数据源,直到找到最新的数据。first()和takeFirst()运算符的比较对于此设计模式,可以选择first()和takeFirst()运算符。两种调用方式的区别在于,如果所有数据源的数据都过期了,没有有效数据作为事件发送,first()会抛出NoSuchElementException(译者注:first()操作符都返回false),而takeFirst()运算符直接调用完成操作而不抛出任何异常。使用哪个运算符完全取决于您是否需要显式处理丢失的数据。可以在此处查看代码示例,上面所有代码的示例实现:https://github.com/dlew/rxjava-multiple-sources-sample。如果你想要一个真实的例子,请查看GfycatApp,它在获取数据时使用了这种模式。该项目并没有使用上面显示的所有函数(因为不需要),而是演示了concat().first()的基本用法。