RxHttp, network wide Http cache optimal solution, final battle

  1. READ_CACHE_FAILED_REQUEST_NETWORK

    In this mode, the cache is read first. After reading successfully, it returns directly; Otherwise, the network will be requested (if the request is successful, write to the cache)

  2. REQUEST_NETWORK_FAILED_READ_CACHE

    In this mode, the network is requested first, the request is successful, the cache is written and returned; Otherwise, read the cache

3. Set cache policy for individual requests

Set a separate cache policy for a single request through Rxhttp#setCache(CacheMode), as follows:

RxHttp.get("/service/...")
    .setCacheValidTime(10 * 1000) //The current request cache is valid for 10 seconds
    .setCache(CacheMode.READ_CACHE_FAILED_REQUEST_NETWORK) //The current request reads the cache first, and then requests the network after it fails
    .asString()
    .subscribe(s -> {
        //Successful callback 
    }, throwable -> {
        //Failed callback 
    }); 

The above code sets a separate cache policy for a single request, in which the effective length is 10 seconds. The cache mode is to read the cache first and then request the network after failure. If not set, the global cache policy is used.

Note: before setting a separate cache mode / cache effective length, be sure to set the cache storage directory and the maximum cache Size, otherwise it will be invalid

4. About CacheKey

CacheKey plays a very important role in the cache module of RxHttp. The internal cache is read, written and deleted through CacheKey. For different requests, ensure the uniqueness of the CacheKey; For the same request, these two features are very important to ensure the static nature of the CacheKey, otherwise the cache will become meaningless.

Why do you say that? Please look down.

4.1. Generation rules of internal CacheKey

RxHttp will generate a unique CacheKey for each request according to certain rules. The rules are as follows:

NoBodyParam:

Splice the added parameters after the url, such as cachekey = url? Key = value & key1 = value1..., Get and Head type requests follow this rule

FormParam:

Like NoBodyParam, the added parameters are spliced after the url, such as cachekey = url? Key = value & key1 = value1..., and the xxxForm type request follows this rule

JsonParam:

After the added parameters are converted into Json string jsonStr, they are added after the url. For example, CacheKey = url?json=jsonStr. The xxxJson type request follows this rule

JsonArrayParam:

The same as JsonParam, after the added parameters are converted into the Json string jsonStr, they are added after the url, such as CacheKey = url?json=jsonStr, and the xxxJsonArray type request follows this rule

The above four rules can be viewed in the getCacheKey() method of the corresponding Param class

4.2. User defined CacheKey

If the above rules cannot meet your business needs, RxHttp also provides two ways to customize the CacheKey, as follows:

1. Specify a CacheKey for a single request through the RxHttp#setCacheKey(String) method

RxHttp.get("/service/...")
    .setCacheKey("Custom CacheKey")  //Custom CacheKey
    .asString()
    .subscribe(s -> {
       //Successful callback
    }, throwable -> {
       //Failed callback
    }); 

2. By customizing Param and overriding getCacheKey() method, the generation rules of CacheKey for a certain type of request are as follows:

@Param(methodName = "postEncryptForm")
public class PostEncryptFormParam extends FormParam {

    public PostEncryptFormParam(String url) {
        super(url, Method.POST);
    }

    @Override
    public String getCacheKey() {
        String cacheKey = null;
        String simpleUrl = getSimpleUrl(); //Get Url
        Headers headers = getHeaders();//Get the added request header
        List<KeyValuePair> keyValuePairs = getKeyValuePairs(); //Get the added parameters
        cacheKey = "according to url/Request header/Parameters, custom rules, generate CacheKey";
        return cacheKey;
    }
} 

Note: to customize the CacheKey, you must ensure the uniqueness of the CacheKey. If it is repeated, the existing cache will be overwritten

4.3 uniqueness

Uniqueness is to ensure that different requests have different cachekeys. If it is the same, it will cause cache disorder.

for instance:

There are two different requests, A and B. the CacheKey and cache mode are the same, and the cache mode is READ_CACHE_FAILED_REQUEST_NETWORK, that is, read the cache first, and then request the network after failure.

At this time, A sends A request first. The steps are: read cache failure - > request Network - > request success, write cache - > end;

Then, B initiates a request. The steps are: read cache succeeded - > end;

Because the cachekeys of A and B are the same, when B reads the cache, it reads A's. Moreover, if the cache mode of B is REQUEST_NETWORK_FAILED_READ_CACHE. At this time, if B's request is successful, when writing the cache, because the CacheKey is the same, it will overwrite A's cache. The next time A reads the cache, it will read B's cache, which is what I call cache disorder.

4.4 static performance

What is static? My definition of it is: the same request is sent multiple times. Ensure that the CacheKey is consistent. Otherwise, the cache will be meaningless.

Imagine that each time a request is sent, the current timestamp must be carried, as follows:

RxHttp.get("/service/...")   
    .add("currentTime", System.currentTimeMillis()) 
    .setCache(CacheMode.READ_CACHE_FAILED_REQUEST_NETWORK) //The current request reads the cache first, and then requests the network after it fails
    .asString()    
    .subscribe(s -> {       
      //Successful callback 
    }, throwable -> {       
      //Failed callback 
    }); 

In the above code, each time a request is initiated, the timestamp is different, resulting in different cachekeys generated internally each time, so that the same cache will be written every time without overwriting. What's more, every time the cache is read, it will fail. How can we avoid this situation? Yes, as described earlier, customizing the cachekey can solve this problem. Is there a simpler way? Yes, look down.

Eliminate parameters that do not participate in CacheKey assembly

We can call RxHttpPlugins.setExcludeCacheKeys(String... keys) method to set parameters that do not participate in CacheKey assembly, that is, eliminate these parameters. For the above questions, you can do this:

RxHttpPlugins.setExcludeCacheKeys("currentTime")  //Variable parameter. Multiple key s can be passed in 

At this time, when the request is sent, the current timestamp will not participate in the assembly of CacheKey, so as to ensure that the CacheKey is the same every time the request is initiated, which is what I call static

5. Expand

Here, someone may ask me, I have such a business scenario: open the app, display the cached data in the list, and then request the network to pull the latest data. How can I implement it with RxHttp?

For this scenario, we need a cache mode, that is, read the cache first and continue to request the network whether it is successful or not. However, in RxHttp's 5 cache modes, what if there is no such mode? Now that it has been proposed, there must be a way to realize this scenario through the combination of two modes, as follows:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        //Send a request to read only the cache
        requestData(CacheMode.ONLY_CACHE);  
        //Then, after sending a network request, write the cached request after success
        requestData(CacheMode.NETWORK_SUCCESS_WRITE_CACHE);
    }

    //get data
    public void requestData(CacheMode cacheMode) {
        RxHttp.get("/service/...")
### Recommended learning materials

***

* **Brain map**
  ![360┬░Comprehensive performance tuning](https://img-blog.csdnimg.cn/img_convert/0dd0d43b27b44687f47ed436d97be982.png)
  ![](https://img-blog.csdnimg.cn/img_convert/49d0e9da2d06ef37b8d45316b917a114.png)
  ![](https://img-blog.csdnimg.cn/img_convert/a1ea1fa5a1ff52922d5030eb27b63a33.png)
  **[CodeChina Open source projects:< Android Summary of study notes+Mobile architecture video+Real interview questions for large factories+Project practice source code](https://codechina.csdn.net/m0_60958482/android_p7)**

VHbHzpXx-1630939519092)]
  [External chain picture transfer...(img-bTcwZdKe-1630939519093)]
  **[CodeChina Open source projects:< Android Summary of study notes+Mobile architecture video+Real interview questions for large factories+Project practice source code](https://codechina.csdn.net/m0_60958482/android_p7)**

Tags: Android Design Pattern Cache http memcached

Posted on Mon, 06 Sep 2021 22:53:07 -0400 by patricklcam