How to cache the response in google cloud endpoint

2019-06-02 19:17发布

I'm making an android app which uses google cloud endpoints as the backend. So I'm making request from the app. I want to cache the response of these requests in memory as well as storage.

I want to cache the response on the phone, so that I don't have to make unnecessary repeated network requests.

I searched the internet for some inbuilt solution but couldn't find anything like that in the api provided by google.

There's a total of about 2MB data that I want to cache. This data is spread over 20 end point requests.

What are my best options to implement such a cache?

2条回答
Deceive 欺骗
2楼-- · 2019-06-02 19:51

You can implement an amazing library called android-easy-cache

the sample implementation is shown in my answer here

查看更多
Root(大扎)
3楼-- · 2019-06-02 19:57

I'm going to answer my own question so that it can help someone until there's a more clean solution available.

I'm using this library for caching responses: https://github.com/vincentbrison/android-easy-cache

  1. GCE result is a GenericJson. Serialize the response using this SerializationUtil
  2. Use this code to create DualCache library boilerplate. dualCacheByteArray for caching the response and dualCacheDate for keeping track of time_to_live_for_response

    public static final int APP_CACHE_VERSION = 1;
    public static final String CACHE_ID = "cache_id_string";
    public static final String CACHE_ID_DATE = "cache_id_date";
    public static final int RAM_CACHE_SIZE = 5 * 1024 * 1024; // 5 mb
    public static final int DISK_CACHE_SIZE = 15 * 1024 * 1024; //15 mb
    public static final int RAM_CACHE_SIZE_DATE = 1 * 1024 * 1024; // 5 mb
    public static final int DISK_CACHE_SIZE_DATE = 3 * 1024 * 1024; //15 mb
    
    
    private DualCache<byte[]> dualCacheByteArray;
    private DualCache<Date> dualCacheDate;
    
    public DualCache<byte[]> getDualCacheByteArray() {
    if (dualCacheByteArray == null) {
        dualCacheByteArray = new DualCacheBuilder<byte[]>(Constants.CACHE_ID, Constants.APP_CACHE_VERSION, byte[].class)
                .useReferenceInRam(Constants.RAM_CACHE_SIZE, new SizeOf<byte[]>() {
                    @Override
                    public int sizeOf(byte[] object) {
                        return object.length;
                    }
                })
                .useDefaultSerializerInDisk(Constants.DISK_CACHE_SIZE, true);
        }
        return dualCacheByteArray;
    }
    
    public DualCache<Date> getDualCacheDate() {
    if (dualCache == null) {
        dualCacheDate = new DualCacheBuilder<Date>(Constants.CACHE_ID_DATE, Constants.APP_CACHE_VERSION, Date.class)
                .useReferenceInRam(Constants.RAM_CACHE_SIZE_DATE, new SizeOf<Date>() {
                    @Override
                    public int sizeOf(Date date) {
                        byte[] b = new byte[0];
                        try {
                            ByteArrayOutputStream baos = new ByteArrayOutputStream();
                            ObjectOutputStream oos = new ObjectOutputStream(baos);
                            oos.writeObject(date);
                            oos.flush();
                            byte[] buf = baos.toByteArray();
                            return buf.length;
                        } catch (IOException e) {
                            Log.e("some prob", "error in calculating date size for caching", e);
                        }
                        return sizeOf(date);
                    }
                })
                .useDefaultSerializerInDisk(Constants.DISK_CACHE_SIZE_DATE, true);
        }
        return dualCacheDate;
    }
    
  3. Now use the above DualCaches to cache your response.

    getDualCacheByteArray().put(YOUR_RESPONSE_CACHE_KEY, serializedProduct);
    getDualCacheDate().put(YOUR_RESPONSE_CACHE_KEY, new Date());
    
  4. Before making a new request using google cloud endpoints, you should check in dual cache if the old response is already present in cache

    public byte[] getCachedGenericJsonByteArray(String key, int cacheExpireTimeInMinutes) {
        Date cachingDate = getDualCacheDate().get(key);
        if(cachingDate!=null) {
            long expirationTime = TimeUnit.MILLISECONDS.convert(cacheExpireTimeInMinutes, TimeUnit.MINUTES);
            long timeElapsedAfterCaching = new Date().getTime() - cachingDate.getTime();
            if (timeElapsedAfterCaching >= expirationTime) {
                //the cached data has expired
                return null;
            } else {
                byte[] cachedGenericJsonByteArray = getDualCacheByteArray().get(key);
                return cachedGenericJsonByteArray;
            }
        } else {
        //result for this key was never cached or is cleared
        return null;
        }
    }
    

if the cached byte array is not null, then deserialize it using SerializationUtil and use it as a cached response, else make a new request from google cloud endpoints

EDIT : Using serialization util may not be necessary in every case as pointed out by Sanket Berde in other answer

查看更多
登录 后发表回答