package in.srain.cube.cache;
import android.content.Context;
import in.srain.cube.concurrent.SimpleExecutor;
import in.srain.cube.concurrent.SimpleTask;
import in.srain.cube.diskcache.CacheEntry;
import in.srain.cube.diskcache.DiskCache;
import in.srain.cube.diskcache.lru.SimpleDiskLruCache;
import in.srain.cube.util.CLog;
import java.io.File;
import java.io.IOException;
/**
* It's easy to use.
* Auto open.
*/
public class DiskCacheProvider {
public interface AsyncTaskEventHandler {
public void onEvent(int type);
}
public static final boolean DEBUG = true;
protected static final String LOG_TAG = "cube-disk-cache-provider";
public static final byte TASK_INIT_CACHE = 1;
public static final byte TASK_CLOSE_CACHE = 2;
public static final byte TASK_FLUSH_CACHE = 3;
protected DiskCache mDiskCache;
private boolean mIsDelayFlushing = false;
private final Object mDiskCacheLock = new Object();
private boolean mDiskCacheStarting = true;
private boolean mDiskCacheReady = false;
private AsyncTaskEventHandler mAsyncTaskEventHandler;
public void setAsyncTaskEventHandler(AsyncTaskEventHandler handler) {
mAsyncTaskEventHandler = handler;
}
public DiskCacheProvider(DiskCache diskCache) {
mDiskCache = diskCache;
}
public static DiskCacheProvider createLru(Context context, File path, long size) {
SimpleDiskLruCache simpleDiskLruCache = new SimpleDiskLruCache(path, 1, size);
DiskCacheProvider provider = new DiskCacheProvider(simpleDiskLruCache);
return provider;
}
public void write(String key, String str) {
if (key == null) {
return;
}
try {
CacheEntry cacheEntry = getDiskCache().beginEdit(key);
cacheEntry.setString(str);
cacheEntry.commit();
} catch (IOException e) {
e.printStackTrace();
}
}
public String read(String fileCacheKey) {
try {
CacheEntry cacheEntry = getDiskCache().getEntry(fileCacheKey);
if (cacheEntry != null) {
return cacheEntry.getString();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* initiate the disk cache
*/
public void openDiskCacheAsync() {
if (DEBUG) {
CLog.d(LOG_TAG, "%s: initDiskCacheAsync", mDiskCache);
}
synchronized (mDiskCacheLock) {
mDiskCacheStarting = true;
new FileCacheTask(TASK_INIT_CACHE).executeNow();
}
}
/**
* close the disk cache
*/
public void closeDiskCacheAsync() {
if (DEBUG) {
CLog.d(LOG_TAG, "%s: closeDiskCacheAsync", mDiskCache);
}
new FileCacheTask(TASK_CLOSE_CACHE).executeNow();
}
/**
* flush the data to disk cache
*/
public void flushDiskCacheAsync() {
if (DEBUG) {
CLog.d(LOG_TAG, "%s, flushDishCacheAsync", mDiskCache);
}
new FileCacheTask(TASK_FLUSH_CACHE).executeNow();
}
/**
* flush the data to disk cache
*/
public void flushDiskCacheAsyncWithDelay(int delay) {
if (DEBUG) {
CLog.d(LOG_TAG, "%s, flushDiskCacheAsyncWithDelay", delay);
}
if (mIsDelayFlushing) {
return;
}
mIsDelayFlushing = true;
new FileCacheTask(TASK_FLUSH_CACHE).executeAfter(delay);
}
/**
* If disk is not read, will prepare it first.
*
* @return
*/
public DiskCache getDiskCache() {
if (!mDiskCacheReady) {
if (DEBUG) {
CLog.d(LOG_TAG, "%s, try to access disk cache, but it is not open, try to open it.", mDiskCache);
}
openDiskCacheAsync();
}
synchronized (mDiskCacheLock) {
while (mDiskCacheStarting) {
try {
if (DEBUG) {
CLog.d(LOG_TAG, "%s, try to access, but disk cache is not ready, wait", mDiskCache);
}
mDiskCacheLock.wait();
} catch (InterruptedException e) {
}
}
}
return mDiskCache;
}
/**
* A helper class to encapsulate the operate into a Work which will be executed by the Worker.
*/
private class FileCacheTask extends SimpleTask {
private byte mTaskType;
private FileCacheTask(byte taskType) {
mTaskType = taskType;
}
@Override
public void doInBackground() {
try {
doWork();
} catch (IOException e) {
e.printStackTrace();
}
}
private void doWork() throws IOException {
switch (mTaskType) {
case TASK_INIT_CACHE:
synchronized (mDiskCacheLock) {
if (DEBUG) {
CLog.d(LOG_TAG, "begin open disk cache: " + mDiskCache);
}
mDiskCache.open();
mDiskCacheReady = true;
mDiskCacheStarting = false;
if (DEBUG) {
CLog.d(LOG_TAG, "disk cache open successfully, notify all lock: " + mDiskCache);
}
mDiskCacheLock.notifyAll();
}
break;
case TASK_CLOSE_CACHE:
mDiskCache.close();
break;
case TASK_FLUSH_CACHE:
mDiskCache.flush();
break;
default:
break;
}
}
@Override
public void onFinish(boolean canceled) {
if (mAsyncTaskEventHandler != null) {
mAsyncTaskEventHandler.onEvent(mTaskType);
}
}
void executeNow() {
SimpleExecutor.getInstance().execute(this);
}
void executeAfter(int delay) {
postDelay(new Runnable() {
@Override
public void run() {
executeNow();
}
}, delay);
}
}
}