No more wasting APIs calls on restoring your instance state.
Not a promotion but my bud wiseAss aka Ryan Kay, is trying hard to share lots of information about software engineering specially related to Android and Kotlin, please do support him by purchasing his learning material , if you can't please do share these links, and his youtube channel for awesome free content.
🙇🏻♂️ Thanks a lot! Follow Ryan's Youtube. Please continue without disturbance...
There are many variations of Repository pattern just like any other Architectural Pattern and can be bend according to the needs of the Software, but the core responsibility of Repository is to provide a clean API so that the rest of the app can retrieve it’s data easily.
They consume various data sources from the app to get the data. These data sources could be local models, web services, and caches.
Today’s article is an example of how you can implement LRU caching into the repository so you can save some API/Database calls.
Step 1 : Create a Tracker for the source of the data. 👩💻
We need to have a field that can be used to figure out from which origin does the data source is being fetched from, for that you can use an Enum class.
Step 2 : Decide the Type to be Cached. 🤔
Since cache stores multiple type of data, storing Any in the cache could be a good option but can we do better?, Yes by using a marker interface, that could help in designing a contact which could store meta-information related to cached data entry, for example data source which we have created in step 1 and something like a expire time/stale time which can be used to invalidate data in cache.
Step 3 : Implementing LRU Cache using LinkedHashMap 🤩
LinkedHashMap is a blend of a linked list and a hash map. By default when you iterate over it, you get back the insertion order. This is useful when you want to build up a dictionary of entries that should be fast to access, but also have a very specific order.
One of the constructors is used to create this type of LinkedHashMap: LinkedHashMap(initialCapacity, loadFactor, true) - the true means "accessOrder" instead of the default, which is "insertionOrder" is preserved.
Using this feature of LinkedHashMap is the ability to also retrieve elements in the order in which they were last accessed.
Another factor that is very special is that we can also automatically remove the eldest entry if we have exceeded our maximum number. To do that we subclass LinkedHashMap and add a maxEntries field. We also override the removeEldestEntry(Map.Entry<K, V> eldest) method from LinkedHashMap to return true when we have reached our maximum size.
These features make it a perfect candidate to behave as a LRU cache.
Step 4 : Skeletal Class for BaseRepository 💻
You can create a Skeletal class/baseClass that can abstract away repetitive code of creating LRU cache and common functions to get entry from cache.
Step 5 : Creating Cacheable DTOs 📝
Your data classes need to extend Cacheable interface , so that they could be compatible with the cache, and we can associate functionality that decide data-source origin and add logic that defines when the item is invalidated into the cache.
Behavioural Example. 👷🏻♀️
Implementation example :
Cache storing the value :
Cache expiring value after stale time passed :
Create object if not present in cache and then cache :
Read from cache
If value is added to filled cache
Update#1 [7 Sept 2020] : From Reddit user name Volt316, pointed me out that android officially have LRU cache file pre implemented similar to what I did, you can checkout from here , also a DiskCache for which you can checkout from here and here (I will do a simplified version for it in future). Thanks Volt316!
From the above example, we have successfully implemented a LRU cache in our repository. It's a very easy example you can mold it according to your requirements.
Hope you find it informative and if you have any feedback or post request or want to subscribe to my mailing list forms are below.
Until next time. Happy Hacking! 👩💻
Enjoy the article?
a clap is much appreciated if you enjoyed. No sign up or cost associated :)