Implement Caching in Android Using RxJava Operators
The cache on your Android phone is a collection of little pieces of information that your apps and web browser utilize to improve efficiency. RxOperator is essentially a function that specifies the observable, as well as how and when it should emit the data stream. In RxJava, there are hundreds of operators to choose from. The majority of operators act on an Observable and return another Observable. This allows you to apply these operators in a chain, one after the other. Each operator in the chain alters the Observable that is the outcome of the preceding operator’s activity.
First, we must comprehend why caching is beneficial. Caching is extremely beneficial in the following scenarios:
- Lowering Data Usage: By caching network responses, we may reduce network calls.
- Fast and Rapid: Fetch the data as quickly as possible
Geek wondered about the Data Sources
Assume you have some data that you want to get from the network. You could just connect to the network each time I need the data, but storing it on disc and in memory would be far more efficient.
The logical next step is to save sources as they arrive. You’ll never notice any savings if you don’t store the results of network queries to disc or cache disc requests in memory!
Types of caching
It can be classified into two types
- Memory cache
- Disk cache
Memory Cache: It stores data in the application’s memory. The data is ejected if the application is terminated. Only applicable within the same application session. Because the data is in memory, the memory cache is the quickest cache to access it.
Disk Cache: This function stores data to the disc. The data is kept even if the program is terminated. Even after the application has restarted, it is still useful. Because this is an I/O operation, it is slower than memory cache.

Image #1. Understanding Caching in Android.
When the user launches the program for the first time, there will be no data in memory and no data in the disc cache. As a result, the application will need to make a network call to retrieve the data. It will retrieve data from the network, store it to disc, retain it in-memory cache, and then return the data.
If the user returns to the same screen during the same session, the data will be retrieved from the memory cache relatively quickly. If the user exits and restarts the program, it will get the data from the disc cache, save it in the memory cache, and return the data. Because every data has validity, the cache will only return the data if it is valid at the moment of retrieval.
We now understand how caching works, prior to it the DataSource will manage three data sources as follows:
- Memory
- Disk
- Network
Example 1: A Data Model
class GFG { //Declaring a string public String gfg; }
Example 2: Memory data source
// Main class // gfgDataSource class GFG { // Member variables of this class private Data gfgData; // Method 1 public Observable<Data> 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"; } }
Example 3: A Disk Data Source
// Main class // gfgDiskData class GFG { // Member variables of this class private Data gfgData; // Method 1 public Observable<Data> 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"; } }
Implementation:
Example
// 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<Data> getDataFromMemory() { // Getting the data from Mem // using the cache return gfgmemoryData.getData(); } // Method 3 public Observable<Data> getDataFromDisk() { // Getting the data from Disk return gfgDiskData.getData().doOnNext( data -> gfgmemoryData.cacheInMemory(data)); } // Method 4 public Observable<Data> getDataFromNetwork() { // No prior cache available, using network // slow way. return gfgNetwork.getData().doOnNext(data -> { gfgDiskData.saveToDisk(data); gfgmemoryData.cacheInMemory(data); }); } }
In this case, we utilized the Concat operator to keep the order of the observables, which is first checked on memory, then in the disc, and finally in the network. As a result, the Concat operator will assist us in keeping the order. This operator ensures that if we receive the data from memory, it does not allow the other observables (disc, network) to do anything and that if we get the data from the disc, it does not let the network observable do anything. As a result, there is no duplicate work. This is where the firstElement operator comes in.
Conclusion:
This is everything about the RxJava Operators, hope this article cleared the air of the topic and any dust if confusion. Using the RxJava Operators, we can create caching in Android apps.
Please Login to comment...