package net.mvla.mvhs.schedulecalendar.cache; import android.content.Context; import android.util.LruCache; import com.jakewharton.disklrucache.DiskLruCache; import net.mvla.mvhs.BuildConfig; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import rx.Observable; import rx.Single; import rx.functions.Func1; import rx.schedulers.Schedulers; public class DiskMemoryCache<T> { private LruCache<String, T> memoryCache; private String name; private Mapper<T> mapper; private DiskLruCache diskCache; private Context context; private int maxDiskBytes; public DiskMemoryCache(Context context, int maxDiskBytes, int maxMemoryItems, String name, Mapper<T> mapper) { this.context = context; this.maxDiskBytes = maxDiskBytes; this.name = name; this.mapper = mapper; memoryCache = new LruCache<>(maxMemoryItems); try { diskCache = initCache(context, name); } catch (IOException e) { e.printStackTrace(); } } private DiskLruCache initCache(Context context, String fileName) throws IOException { File cacheFile = new File(context.getCacheDir().getCanonicalPath() + File.separator + fileName); return DiskLruCache.open(cacheFile, BuildConfig.VERSION_CODE, 1, maxDiskBytes); } public void put(String key, T item) { memoryCache.put(key, item); try { DiskLruCache.Editor edit = diskCache.edit(key); OutputStream out = edit.newOutputStream(0); mapper.toStream(out, item); out.close(); edit.commit(); } catch (IOException e) { e.printStackTrace(); } } public Observable<T> get(final String key, Func1<T, Boolean> filter) { Single<T> memory = Single.just(memoryCache.get(key)); final Single<T> disk = Single.fromCallable(() -> { DiskLruCache.Snapshot snapshot = diskCache.get(key); InputStream inputStream = snapshot.getInputStream(0); T t = mapper.fromStream(inputStream); inputStream.close(); return t; }).doOnSuccess(object -> memoryCache.put(key, object)).onErrorReturn(throwable -> null); return Single.concat(memory, disk) .subscribeOn(Schedulers.io()) .takeFirst(filter); } public interface Mapper<T> { T fromStream(InputStream inputStream) throws IOException; void toStream(OutputStream outputStream, T item) throws IOException; } }