stephanenicolas / robospice

Repo of the Open Source Android library : RoboSpice. RoboSpice is a modular android library that makes writing asynchronous long running tasks easy. It is specialized in network requests, supports caching and offers REST requests out-of-the box using extension modules.
Apache License 2.0
2.95k stars 545 forks source link

Robospice CachePolicy #338

Open abreu-dev opened 10 years ago

abreu-dev commented 10 years ago

Hi. i am digging into Robospice code to understand how it really works. I think executing a request is not simple. We have, setDirtyCache, setOffline, and a lot of execute methods in the spiceManager.

1) If i want to get some data from cache, i do:

sipceManager.getFromCache(MyObject.Class, requestCacheKey, DurationInMillis.ONE_MINUTE, requestListener);

This method will just execute a CachedSpiceRequest under the hood with a DummySpiceRequest (this DummySpiceRequest doesnt have a higher priority, why?), and will put setOffline flag to true. The cache policy here is CachePolicy.CACHE_ONLY.

2) If i want to get some data from cache if not expired or make a network request if cache expired, i do:

spiceManager.execute(myRequest, requestCacheKey, DurationInMillis.ONE_MINUTE, requestListener);

The cache policy here is CachePolicy.CACHE_FIRST.

3) If i want to get data from cache and load from network if cache expired, i do:

spiceManager.getFromCacheAndLoadFromNetworkIfExpired(request, requestCacheKey, DurationInMillis.ONE_MINUTE, new MyRequestListener());

private class MyRequestListener implements RequestListener<Object>, RequestProgressListener {

    // 1 - CACHE, 2 - NETWORK
    private int source = 0;

    @Override
    public void onRequestFailure(SpiceException arg0) {
        // FAIL
    }

    @Override
    public void onRequestSuccess(Object obj) {
        if (source == 1) {
            // from cache
        } else {
            // from network
        }
    }

    @Override
    public void onRequestProgressUpdate(RequestProgress progress) {
        if (progress.getStatus() == ProgressStatus.READING_FROM_CACHE)
            source = 1;
        } else if (progress.getStatus() == ProgressStatus.READING_FROM_NETWORK) {
            source = 2;
        }
    }
}

The cache policy here is CachePolicy.BOTH. Is this the best way to know if the data were retrieved from cache or network ?

Conclusion:

I think we just need two executes methods in spiceManager.

spiceManager.execute(request) and spiceManager.execute(request, requestListener)

and we can execute requests like this:

requestA.setCacheKey("user{1012}:followers");
requestA.setCacheDuration(DurationInMillis.ONE_MINUTE);
requestA.setCachePolicy(CachePolicy.CACHEFIRST);

requestB.setCacheKey("user{1012}:messages");
requestB.setCachePolicy(CachePolicy.BOTH);

spiceManager.execute(requestA, aRequestListener);
spiceManager.execute(requestB, bRequestListener);

CACHE POLICIES:

CachePolicy.NOCACHE: This policy will not use any caching, and will execute every request online. Use this policy if your application is dependant on data that is shared between multiple users and always needs to be up to date.

CachePolicy.CACHEONLY: This policy will only retrieve data from the cache, and will not use any network connection. Use this policy in combination with another policy, to allow for quick response times without requiring a network connection for specific operations.

CachePolicy.CACHEFIRST: This policy will first attempt to retrieve data from the cache. If the data has been cached, it will be returned. If the data does not exist in the cache, the data will be retrieved from "loadDataFromNetwork" and the cache will be updated. Use this policy if your application can display data that doesn't change very often but you still want local updates.

CachePolicy.CACHEFIRST_NOREFRESH: This policy will first attempt to retrieve data from the cache. If the data has been cached, it will be returned. If the data does not exist in the cache, the data will be retrieved from "loadDataFromNetwork" but the cache will not be updated with the new results. Use this policy if you want to set default results, however if a request is made that cannot return these defaults a live request will be made (without modifying those default values)

CachePolicy.NETWORKFIRST: This policy will execute the request on the network, and will store the result in the cache. If the network execution fails, the results will be pulled from the cache. Use this policy if your application wants the latest data but you still want responsiveness if a connection is lost

CachePolicy.BOTH: This policy will first retrieve an element from the cache, and then it will attempt to execute the request on line.

P.S.: English is not my native language

Thanks :)

stephanenicolas commented 10 years ago

@andreabreu-me I have read your thread a long time ago. I find it interesting but really I don't have enough time to read it in depth and try to see if I would like to implement it or not. But it really looks interesting...

I plan the feature for 1.5.0, hoping to get some time or some contribution for it.