Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
R

RxCache

> 编程语言
Open source

Reactive caching library for Android and Java

2.3K stars0 likes1 views
WebsiteGitHub

About

Reactive caching library for Android and Java

:warning: This repository is no longer mantained consider using Room as an alternative :warning:

RxCache

中文文档

For a more reactive approach go here.

The goal of this library is simple: caching your data models like Picasso caches your images, with no effort at all.

Every Android application is a client application, which means it does not make sense to create and maintain a database just for caching data.

Plus, the fact that you have some sort of legendary database for persisting your data does not solves by itself the real challenge: to be able to configure your caching needs in a flexible and simple way.

Inspired by Retrofit api, RxCache is a reactive caching library for Android and Java which turns your caching needs into an interface.

When supplying an observable, single, maybe or flowable (these are the supported Reactive types) which contains the data provided by an expensive task -probably an http connection, RxCache determines if it is needed to subscribe to it or instead fetch the data previously cached. This decision is made based on the providers configuration.

java
Observable<List<Mock>> getMocks(Observable<List<Mock>> oMocks);

Setup

Add the JitPack repository in your build.gradle (top level module):

gradle
allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

And add next dependencies in the build.gradle of the module:

gradle
dependencies {
    compile "com.github.VictorAlbertos.RxCache:runtime:1.8.3-2.x"
    compile "io.reactivex.rxjava2:rxjava:2.1.6"
}

Because RxCache uses internally Jolyglot to serialize and deserialize objects, you need to add one of the next dependency to gradle.

gradle
dependencies {
    // To use Gson 
    compile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.4'
    
    // To use Jackson
    compile 'com.github.VictorAlbertos.Jolyglot:jackson:0.0.4'
    
    // To use Moshi
    compile 'com.github.VictorAlbertos.Jolyglot:moshi:0.0.4'
}

Usage

Define an interface with as much methods as needed to create the caching providers:

…

RxCache exposes evictAll() method to evict the entire cache in a row.

RxCache accepts as argument a set of classes to indicate how the provider needs to handle the cached data:

  • A Reactive type is the only object required to create a provider. This Reactive type must be equal to the one specified by the returning value of the provider.
  • EvictProvider allows to explicitly evict all the data associated with the provider.
  • @ProviderKey is an annotation for provider methods that is highly recommended to use and proguard users MUST use this annotation, if not used the method names will be used as provider keys (cache keys) and proguard users will quickly run into problems, please see Proguard for detailed information. Using the annotaiton is also useful when not using Proguard as it makes sure you can change your method names without having to write a migration for old cache files.
  • EvictDynamicKey allows to explicitly evict the data of an specific DynamicKey.
  • EvictDynamicKeyGroup allows to explicitly evict the data of an specific DynamicKeyGroup.
  • DynamicKey is a wrapper around the key object for those providers which need to handle multiple records, so they need to provide multiple keys, such us endpoints with pagination, ordering or filtering requirements. To evict the data associated with one particular key use EvictDynamicKey.
  • DynamicKeyGroup is a wrapper around the key and the group for those providers which need to handle multiple records grouped, so they need to provide multiple keys organized in groups, such us endpoints with filtering AND pagination requirements. To evict the data associated with the key of one particular group, use EvictDynamicKeyGroup.

Supported annotations:

  • @LifeCache sets the amount of time before the data would be evicted. If @LifeCache is not supplied, the data will be never evicted unless it is required explicitly using EvictProvider, EvictDynamicKey or EvictDynamicKeyGroup .
  • @Actionable offers an easy way to perform write operations using providers. More details here
  • @SchemeMigration and @Migration provides a simple mechanism for handling migrations between releases. More details here
  • @Expirable determines if that provider will be excluded from the evicting process or not. More details here
  • @EncryptKey and @Encrypt provides a simple way to encrypt/decrypt the data on persistence layer. More details here

Build an instance of Providers and use it

Finally, instantiate the Providers interface using RxCache.Builder and supplying a valid file system path which would allow RxCache to write on disk.

java
File cacheDir = getFilesDir();
Providers providers = new RxCache.Builder()
                            .persistence(cacheDir, new GsonSpeaker())
                            .using(Providers.class);

Putting It All Together

java
interface Providers {

    @ProviderKey("mocks-evict-provider")
    Observable<List<Mock>> getMocksEvictProvider(Observable<List<Mock>> oMocks, EvictProvider evictProvider);

    @ProviderKey("mocks-paginate-evict-per-page")
    Observable<List<Mock>> getMocksPaginateEvictingPerPage(Observable<List<Mock>> oMocks, DynamicKey page, EvictDynamicKey evictPage);

    @ProviderKey("mocks-paginate-evict-per-filter")
    Observable<List<Mock>> getMocksPaginateWithFiltersEvictingPerFilter(Observable<List<Mock>> oMocks, DynamicKeyGroup filterPage, EvictDynamicKey evictFilter);
}
…

Use cases

  • Using classic API RxCache for read actions with little write needs.
  • Using actionable API RxCache, exclusive for write actions.

Classic API RxCache:

Following use cases illustrate some common scenarios which will help to understand the usage of DynamicKey and DynamicKeyGroup classes along with evicting scopes.

List

List without evicting:

java
Observable<List<Mock>> getMocks(Observable<List<Mock>> oMocks);

List evicting:

java
Observable<List<Mock>> getMocksEvictProvider(Observable<List<Mock>> oMocks, EvictProvider evictProvider);

Runtime usage:

java
//Hit observable evicting all mocks
getMocksEvictProvider(oMocks, new EvictProvider(true))

//This line throws an IllegalArgumentException: "EvictDynamicKey was provided but not was provided any DynamicKey"
getMocksEvictProvider(oMocks, new EvictDynamicKey(true))

List Filtering

List filtering without evicting:

java
Observable<List<Mock>> getMocksFiltered(Observable<List<Mock>> oMocks, DynamicKey filter);

List filtering evicting:

java
Observable<List<Mock>> getMocksFilteredEvict(Observable<List<Mock>> oMocks, DynamicKey filter, EvictProvider evictDynamicKey);

Runtime usage:

java
//Hit observable evicting all mocks using EvictProvider
getMocksFilteredEvict(oMocks, new DynamicKey("actives"), new EvictProvider(true))

//Hit observable evicting mocks of one filter using EvictDynamicKey
getMocksFilteredEvict(oMocks, new DynamicKey("actives"), new EvictDynamicKey(true))

//This line throws an IllegalArgumentException: "EvictDynamicKeyGroup was provided but not was provided any Group"
getMocksFilteredEvict(oMocks, new DynamicKey("actives"), new EvictDynamicKeyGroup(true))

List Paginated with filters

List paginated with filters without evicting:

java
Observable<List<Mock>> getMocksFilteredPaginate(Observable<List<Mock>> oMocks, DynamicKey filterAndPage);

List paginated with filters evicting:

java
Observable<List<Mock>> getMocksFilteredPaginateEvict(Observable<List<Mock>> oMocks, DynamicKeyGroup filterAndPage, EvictProvider evictProvider);

Runtime usage:

java
//Hit observable evicting all mocks using EvictProvider
getMocksFilteredPaginateEvict(oMocks, new DynamicKeyGroup("actives", "page1"), new EvictProvider(true))

//Hit observable evicting all mocks pages of one filter using EvictDynamicKey
getMocksFilteredPaginateEvict(oMocks, new DynamicKeyGroup("actives", "page1"), new EvictDynamicKey(true))

//Hit observable evicting one page mocks of one filter using EvictDynamicKeyGroup
getMocksFilteredPaginateInvalidate(oMocks, new DynamicKeyGroup("actives", "page1"), new EvictDynamicKeyGroup(true))

As you may already notice, the whole point of using DynamicKey or DynamicKeyGroup along with Evict classes is to play with several scopes when evicting objects.

The above examples declare providers which their method signature accepts EvictProvider in order to be able to concrete more specifics types of EvictProvider at runtime.

But I have done that for demonstration purposes, you always should narrow the evicting classes in your method signature to the type which you really need. For the last example, I would use EvictDynamicKey in production code, because this way I would be able to paginate the filtered items and evict them per its filter, triggered by a pull to refresh for instance.

Nevertheless, there are complete examples for Android and Java projects.

Actionable API RxCache:

Limitation: This actionable API only support Observable as Reactive type.

This actionable api offers an easy way to perform write operations using providers. Although write operations could be achieved using the classic api too, it's much complex and error-prone. Indeed, the Actions class it's a wrapper around the classic api which play with evicting

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Java

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言