androidioscachingxamarin.iospreloading

Local pre-load and caching layer for REST calls in (Xamarin) apps to reduce wait?


I am relatively new to mobile development and Xamarin. I am making an app they relies entirely on a REST API, and it's very clear that clicking around the app is a quite bad experience because of the constant loads despite they're quite fast.

The solution I've come up with, is calling many of get endpoints asynchronous when the user loads the app and then cache is for a short while.

I can easily implement this myself, but I would end up re-investing the wheel for a problem that I assume every single app that uses REST API's have.

So my question is:

What is the most common approach to pre-load and cache REST data in (Xamarin) apps?

Is it to make a cache layer between the apps local service area, and then start an asynchronous task that caches the endpoints we expect the user to open?


Solution

  • You can make a cache based layer. You need to consider if you want it persisted in memory only or both memory and disk.

    I present a multilevel (memory, disk, network) cache system. I have used this architecture with success. It is works with singleton class and c# events. There can be many subscribers to the handlers. So a UI screen can subscribe to receive when data is available and it can be called back several times per request. The design is that it returns data as quickly as possible (from memory first) but still makes disk and network calls to refresh data. The UI may get called back several times because it will call back quickly with data from memory then call back again once the network request is complete. To help with thread safety you can use locks or use thread safe collections like ConcurrentDictionary or ConcurrentQueue. There's lots more edge case to consider but this is the basic architecture of a multi level cache system with events.

    // pseudo code
    class CacheHelper
    {
    
       // todo: create singleton
    
    RequestData()
    {
    
        if ( data in memory)
        {
            // this quickly gets the app some data
            Fetch data from dictionary/list/etc
            NotifySubscribers( this, data)
        }
    
        if ( data in disk )
        {
           // this gets data persisted after user force closes app then reopens
            Fetch data from sqlite, file storage, etc
            NotifySubscribers( this, data) 
    
            copy data from disk to memory
        }
    
        // always request data from server too to keep it fresh
        RequestLatestDataFromServer();  // you can put a cap on this to limit network requests
    }
    
    HandleRequestLatestDataFromServerComplete( obj, args)
    {
        // this is the data returned from server
         ALSO copy server result to memory and copy to disk
    
         NotifySubscribers( this, data);
    
    }
    
    
    
    /// To use this in a UI class
    ViewDidAppear()
    {
       CacheHelper.Instance.HandleRequestLatestDataFromServerComplete += ReceivedData;
    }
    
    ViewWillDisappear()
    {
       CacheHelper.Instance.HandleRequestLatestDataFromServerComplete -= ReceivedData;
    }
    
    
    void ReceivedData(Object obj, EventArgs args )
    {
         // update your UI
         // This may get called a few times,  for each level of cache retrieved
    }