/* * Copyright (C) 2013 WhiteCat 白猫 (www.thinkandroid.cn) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.ta.util.cache; import java.lang.ref.WeakReference; import java.util.HashMap; import com.ta.common.AsyncTask; import com.ta.util.TALogger; /** * @Title TAFileCacheWork * @Package com.ta.util.cache * @Description 缓存的工作类 * @author 白猫 * @date 2013-1-20 * @version V1.0 */ @SuppressWarnings("rawtypes") public class TAFileCacheWork<ResponseObject extends Object> { private TAFileCache mTAFileCache; private boolean mExitTasksEarly = false; protected boolean mPauseWork = false; private final Object mPauseWorkLock = new Object(); protected static final int MESSAGE_CLEAR = 0; protected static final int MESSAGE_INIT_DISK_CACHE = 1; protected static final int MESSAGE_FLUSH = 2; protected static final int MESSAGE_CLOSE = 3; private HashMap<String, TACacheEntity> mCacheEntityHashMap = new HashMap<String, TACacheEntity>(); private TACallBackHandler<ResponseObject> mCallBackHandler; private TAProcessDataHandler mProcessDataHandler; /** * 从缓存加载数据 * * @param data * 缓存的标识 * @param responseObject * 对缓存结果响应的类 */ @SuppressWarnings("unchecked") public void loadFormCache(Object data, ResponseObject responseObject) { TACacheEntity cacheEntity; String string = String.valueOf(responseObject); if (!mCacheEntityHashMap.containsKey(string)) { cacheEntity = new TACacheEntity(); cacheEntity.setT(responseObject); mCacheEntityHashMap.put(string, cacheEntity); } else { cacheEntity = mCacheEntityHashMap.get(string); } if (data == null) { ; } byte[] buffer = null; if (mTAFileCache != null) { buffer = mTAFileCache.getBufferFromMemCache(String.valueOf(data)); } if (buffer != null) { // 如果返回不为空 if (mCallBackHandler != null) { mCallBackHandler.onSuccess(responseObject, data, buffer); } } else if (cancelPotentialWork(data, cacheEntity)) { final BufferWorkerTask task = new BufferWorkerTask(cacheEntity); final TAAsyncEntity asyncEntity = new TAAsyncEntity(task); if (mCallBackHandler != null) { mCallBackHandler.onStart(responseObject, data); } cacheEntity.setAsyncEntity(asyncEntity); task.executeOnExecutor(AsyncTask.DUAL_THREAD_EXECUTOR, data); } } /** * 设置文件缓存 * * @param fileCache */ public void setFileCache(TAFileCache fileCache) { this.mTAFileCache = fileCache; new CacheAsyncTask().execute(MESSAGE_INIT_DISK_CACHE); } /** * 获取缓存的回调对象 * * @return 如果没有设置,返回为null */ public TACallBackHandler<ResponseObject> getCallBackHandler() { return mCallBackHandler; } public void setCallBackHandler( TACallBackHandler<ResponseObject> callBackHandler) { this.mCallBackHandler = callBackHandler; } public void setProcessDataHandler(TAProcessDataHandler processDataHandler) { this.mProcessDataHandler = processDataHandler; } public TAProcessDataHandler getProcessDataHandler() { return mProcessDataHandler; } /** * 是否退出以前的任务,如果为设置为true则退出以前的Task * * @param exitTasksEarly */ public void setExitTasksEarly(boolean exitTasksEarly) { mExitTasksEarly = exitTasksEarly; setPauseWork(false); } /** * 取消任何挂起的连接到提供给object工作。 * * @param object */ @SuppressWarnings("unchecked") public void cancelWork(ResponseObject responseObject) { TACacheEntity cacheEntity; String string = String.valueOf(responseObject); if (!mCacheEntityHashMap.containsKey(string)) { cacheEntity = new TACacheEntity(); cacheEntity.setT(responseObject); mCacheEntityHashMap.put(string, cacheEntity); } else { cacheEntity = mCacheEntityHashMap.get(string); } final BufferWorkerTask bufferWorkerTask = getBufferWorkerTask(cacheEntity); if (bufferWorkerTask != null) { bufferWorkerTask.cancel(true); } } public boolean cancelPotentialWork(Object data, TACacheEntity cacheEntity) { final BufferWorkerTask responseWorkerTask = getBufferWorkerTask(cacheEntity); if (responseWorkerTask != null) { final Object bitmapData = responseWorkerTask.data; if (bitmapData == null || !bitmapData.equals(data)) { responseWorkerTask.cancel(true); } else { // The same work is already in progress. return false; } } return true; } @SuppressWarnings("unchecked") private BufferWorkerTask getBufferWorkerTask(TACacheEntity cacheEntity) { if (cacheEntity != null) { final TAAsyncEntity asyncEntity = cacheEntity.getAsyncEntity(); if (asyncEntity != null) { return ((BufferWorkerTask) asyncEntity.getBufferWorkerTask()); } } return null; } public void setPauseWork(boolean pauseWork) { synchronized (mPauseWorkLock) { mPauseWork = pauseWork; if (!mPauseWork) { mPauseWorkLock.notifyAll(); } } } protected void initDiskCacheInternal() { if (mTAFileCache != null) { mTAFileCache.initDiskCache(); } } protected void clearCacheInternal() { if (mTAFileCache != null) { mTAFileCache.clearCache(); } } protected void flushCacheInternal() { if (mTAFileCache != null) { mTAFileCache.flush(); } } protected void closeCacheInternal() { if (mTAFileCache != null) { mTAFileCache.close(); mTAFileCache = null; } } protected class CacheAsyncTask extends AsyncTask<Object, Void, Void> { public CacheAsyncTask() { // TODO Auto-generated constructor stub } @Override protected Void doInBackground(Object... params) { switch ((Integer) params[0]) { case MESSAGE_CLEAR: clearCacheInternal(); break; case MESSAGE_INIT_DISK_CACHE: initDiskCacheInternal(); break; case MESSAGE_FLUSH: flushCacheInternal(); break; case MESSAGE_CLOSE: closeCacheInternal(); break; } return null; } } /** * 位图的惟一标识符来存储清除内存和磁盘缓存都TAFileCache与此相关 对象。注意,这包括磁盘访问,所以这是不应当的 上执行的主要/ UI线程。 */ public void clearCache() { new CacheAsyncTask().execute(MESSAGE_CLEAR); } /** * 磁盘缓存初始化TAFileCache与此相关的对象。注意, 这包括磁盘访问,所以这应该不会被执行的主要/ UI 线程。 */ public void initCache() { new CacheAsyncTask().execute(MESSAGE_INIT_DISK_CACHE); } /** * 磁盘缓存刷新TAFileCache与此相关的对象。注意, 这包括磁盘访问,所以这应该不会被执行的主要/ UI 线程。 */ public void flushCache() { new CacheAsyncTask().execute(MESSAGE_FLUSH); } /** * 关闭磁盘缓存与此相关TAFileCache对象。注意,这包括磁盘访问,所以这应该不会被执行的主要/ UI线程。 */ public void closeCache() { new CacheAsyncTask().execute(MESSAGE_CLOSE); } public class BufferWorkerTask extends AsyncTask<Object, Void, byte[]> { private Object data; private final WeakReference<TACacheEntity> cacheEntityReference; public BufferWorkerTask(TACacheEntity cacheEntity) { this.cacheEntityReference = new WeakReference<TACacheEntity>( cacheEntity); } /** * Background processing. */ @Override protected byte[] doInBackground(Object... params) { /* * if (BuildConfig.DEBUG) { Log.d(TAG, * "doInBackground - starting work"); } */ data = params[0]; final String dataString = String.valueOf(data); byte[] buffer = null; // Wait here if work is paused and the task is not cancelled synchronized (mPauseWorkLock) { while (mPauseWork && !isCancelled()) { try { mPauseWorkLock.wait(); } catch (InterruptedException e) { } } } if (mTAFileCache != null && !isCancelled() && getAttachedCacheEntity() != null && !mExitTasksEarly) { buffer = (byte[]) mTAFileCache .getBufferFromDiskCache(dataString); } if (buffer == null && !isCancelled() && getAttachedCacheEntity() != null && !mExitTasksEarly) { if (mProcessDataHandler != null) { buffer = mProcessDataHandler.processData(params[0]); } } if (buffer != null && mTAFileCache != null) { mTAFileCache.addBufferToCache(dataString, buffer); } return buffer; } /** * Once the image is processed, associates it to the imageView */ @SuppressWarnings("unchecked") @Override protected void onPostExecute(byte[] buffer) { // if cancel was called on this task or the "exit early" flag is set // then we're done if (isCancelled() || mExitTasksEarly) { buffer = null; } final TACacheEntity cacheEntity = getAttachedCacheEntity(); if (mCallBackHandler != null && cacheEntity != null) { mCallBackHandler.onSuccess((ResponseObject) cacheEntity.getT(), data, buffer); } } private TACacheEntity getAttachedCacheEntity() { final TACacheEntity cacheEntity = cacheEntityReference.get(); final BufferWorkerTask bufferWorkerTask = getBufferWorkerTask(cacheEntity); if (this == bufferWorkerTask) { return cacheEntity; } return null; } @Override protected void onCancelled(byte[] inputStream) { super.onCancelled(inputStream); synchronized (mPauseWorkLock) { mPauseWorkLock.notifyAll(); } } } }