awinbra
awinbra

Reputation: 704

Robospice: Saving to cache from a SpiceRequest

I have a SpiceRequest whose job is to pre cache a bunch of data, that can then later be loaded individually in separate SpiceRequests.

For example, imagine my app downloads movie times for a particular theater via a SpiceRequest, I need a composite SpiceRequest that downloads and pre caches all the movie times for all theaters in a region.

Lets call this AllMoviesSpiceRequest, its a subclass of SpringAndroidSpiceRequest. Its loadDataFromNetwork() method makes several calls to getRestTemplate().getForObject(). It places all the data into a containing object and returns it.

My plan is when onRequestSuccess is called to call SpiceManager.putInCache for each theater. The problem is the data set for all theaters is large, about 16 MB and its getting an OutOfMemory error due to JsonWriter.string() not being able to serialize a string that large.

Is it possible to cache each theater directly from AllMoviesSpiceRequest as its being downloaded? I'm not sure if its safe to create and call a SpiceManager from a SpiceRequest. Or is there a better approach to take?

Here's some sample code to give you the idea:

public class AllMoviesSpiceRequest extends 
    SpringAndroidSpiceRequest<AllMovieTimes> {

    public AllMovieTimes loadDataFromNetwork() throws Exception {

        AllMovieTimes allMovieTimes = new AllMovieTimes();

        // Get all the theaters
        Theaters theaters = getRestTemplate().getForObject(
            THEATER_JSON_URL + "/" + regionId, Theaters.class);

        // Get all the movies
        for(Theater t : theaters.all()) {
            MovieTimes mt = getRestTemplate().getForObject(
                MOVIES_JSON_URL + "/" + t.getId(), MovieTimes.class);

            allMovieTimes.add(mt);
            // Can I call spiceManager.putInCacheHere???
        }

        // OutOfMemoryError!!!
        return allMovieTimes; 
    }
}

private class AllMoviesRequestListener implements 
    RequestListener<AllMovieTimes> { 

    public void onRequestSuccess(AllMovieTimes allMovieTimes) {

        // Add all the movies to the cache
        for(MovieTime mt : allMovieTimes) {
            spiceManager.putInCache(mt.getCacheKey(), mt);
        }
    }
}

Thanks in advance...

Upvotes: 1

Views: 739

Answers (1)

Snicolas
Snicolas

Reputation: 38168

If your result is too large to be handled by Jackson, that might be a design problem.

Actually having a json of 16 MB is not a good solution for mobile. It would leave your users with an usuable phone for quite a long time, and that's not the way an Android app should work. Even if RS allows to download data in background, you should really care about responsiveness.

In RS all data that result from a REST request will be saved directly and it's not possible to later split them. At least this is true with Jackson/Gson serialization. Json is not a database and can't later give you a selective access to the data.

I could answer that you should move toward a serialization of data in a DB, using ORMLite, possibly with RS ORMLite module, that could allow you to store stuff in separate tables and later you would be able to retrieve them selectively.

Nevertheless, the real answer here is that you should move away from downloading such a large amount of data, or maybe use something like a binary format (protobuf, kryo ?) and store stuff inside a database.

But the simplest, and more common, solution is really to download a smaller amount of data.

Upvotes: 1

Related Questions