📜  使用 RxJava 运算符在 Android 中实现缓存

📅  最后修改于: 2022-05-13 01:58:43.922000             🧑  作者: Mango

使用 RxJava 运算符在 Android 中实现缓存

Android 手机上的缓存是您的应用程序和 Web 浏览器用来提高效率的一小部分信息的集合。 RxOperator 本质上是一个指定 observable 的函数,以及它应该如何以及何时发出数据流。在 RxJava 中,有数百种运算符可供选择。大多数运算符作用于一个 Observable 并返回另一个 Observable。这使您可以一个接一个地在链中应用这些运算符。链中的每个运算符都会更改作为前一个操作员活动结果的 Observable。

首先,我们必须理解为什么缓存是有益的。缓存在以下场景中非常有用:

  • 降低数据使用:通过缓存网络响应,我们可以减少网络调用。
  • Fast and Rapid:尽可能快地获取数据

极客想知道数据源

假设您有一些想要从网络获取的数据。每次我需要数据时,您都可以连接到网络,但将其存储在磁盘和内存中会更有效率。

合乎逻辑的下一步是在源到达时保存它们。如果您不将网络查询的结果存储到磁盘或在内存中缓存磁盘请求,您将永远不会注意到任何节省!

缓存类型

它可以分为两类

  • 内存缓存
  • 磁盘缓存

内存缓存:它将数据存储在应用程序的内存中。如果应用程序终止,数据将被弹出。仅适用于同一应用程序会话。因为数据在内存中,所以内存缓存是访问它的最快的缓存。
磁盘缓存:此函数将数据存储到磁盘。即使程序终止,数据也会保留。即使应用程序重新启动后,它仍然有用。因为这是一个 I/O 操作,所以它比内存缓存慢。

图片#1。了解 Android 中的缓存。

当用户第一次启动程序时,内存中没有数据,磁盘缓存中也没有数据。因此,应用程序将需要进行网络调用来检索数据。它将从网络中检索数据,将其存储到磁盘中,将其保留在内存缓存中,然后返回数据。

如果用户在同一个会话期间返回到同一个屏幕,数据会相对较快地从内存缓存中检索出来。如果用户退出并重新启动程序,它会从磁盘缓存中获取数据,保存在内存缓存中,并返回数据。因为每一个数据都是有效的,所以缓存只会在检索时才返回有效的数据。

我们现在了解缓存是如何工作的,在此之前,DataSource 将管理三个数据源,如下所示

  1. 记忆
  2. 磁盘
  3. 网络

示例 1:数据模型

class GFG {
    
    //Declaring a string
    public String gfg;
}

示例 2:内存数据源

// Main class
// gfgDataSource
class GFG {

  // Member variables of this class
  private Data gfgData;

  // Method 1
  public Observable getData() {

    // Making an observable
    return Observable.create(emitter -> {

      if (gfgData != null) {

        // Emitting the data
        emitter.onNext(gfgData);
      }

      emitter.onComplete();
    });
  }

// Method 2
  void cacheInMemory(Data gfgData) {

    // This keyword refers to current object itself
    this.gfgData = gfgData.clone();

    // Cloning the data for cache
    this.gfgData.source = "Spandan Saxena";
  }
}

示例 3:磁盘数据源

// Main class
// gfgDiskData
class GFG {

  // Member variables of this class
  private Data gfgData;

  // Method 1
  public Observable getData() {
    return Observable.create(shooter -> {

      if (gfgData != null) {

        // Shooting the data to the disk source for usage.
        shooter.onNext(gfgData);
      }

      shooter.onComplete();
    });
  }

  // Method 2
  // Main driver method
  public void saveToDisk(Data gfgData) {

    // Saving the shooted data
    this.gfgData = gfgData.clone();
    this.gfgData.source = "Spandan Saxena";
  }
}

执行:

例子

// Main class
// gfgDataSpace
class GFG {

    // Member variables of this class

    // A memory data source
    private final MemoryDataSource gfgmemoryData;
    // A disk data source
    private final DiskDataSource gfgDiskData;
    // A network data source
    private final NetworkDataSource gfgNetwork;

    // All these are used as needed.

    // Method 1
    public DataSource(MemoryDataSource gfgmemoryData,
                      DiskDataSource gfgDiskData,
                      NetworkDataSource gfgNetwork)
    {

        // Pushing the reference
        // This keyword refers to current object itself
        this.gfgmemoryData = gfgmemoryData;
        this.gfgDiskData = gfgDiskData;
        this.gfgNetwork = gfgNetwork;
    }

    // Method 2
    public Observable getDataFromMemory()
    {

        // Getting the data from Mem
        // using the cache
        return gfgmemoryData.getData();
    }

    // Method 3
    public Observable getDataFromDisk()
    {

        // Getting the data from Disk
        return gfgDiskData.getData().doOnNext(
            data -> gfgmemoryData.cacheInMemory(data));
    }

    // Method 4
    public Observable getDataFromNetwork()
    {

        // No prior cache available, using network
        // slow way.
        return gfgNetwork.getData().doOnNext(data -> {
            gfgDiskData.saveToDisk(data);
            gfgmemoryData.cacheInMemory(data);
        });
    }
}

在这种情况下,我们使用 Concat运算符来保持 observables 的顺序,首先在内存中检查,然后在磁盘中,最后在网络中。因此,Concat运算符将协助我们保持订单。该运算符确保如果我们从内存中接收数据,它不会允许其他可观察对象(磁盘、网络)做任何事情,并且如果我们从磁盘中获取数据,它不会让网络可观察对象做任何事情。因此,没有重复的工作。这就是 firstElement运算符的用武之地。