/**
  * Initializes the disk cache. Note that this includes disk access so this should not be executed
  * on the main/UI thread. By default an ImageProvider does not initialize the disk cache when it
  * is created, instead you should call initDiskCache() to initialize it on a background thread.
  */
 public void initDiskCache() {
   if (DEBUG) {
     Log.d(TAG, "initDiskCache " + this);
   }
   // Set up disk cache
   synchronized (mDiskCacheLock) {
     if (mDiskLruCache == null || mDiskLruCache.isClosed()) {
       if (mDiskCacheDir != null) {
         if (!mDiskCacheDir.exists()) {
           mDiskCacheDir.mkdirs();
         }
         if (FileUtil.getUsableSpace(mDiskCacheDir) > mDiskCacheSize) {
           try {
             mDiskLruCache = DiskLruCache.open(mDiskCacheDir, 1, 1, mDiskCacheSize);
             if (DEBUG) {
               Log.d(TAG, "Disk cache initialized " + this);
             }
           } catch (final IOException e) {
             Log.e(TAG, "initDiskCache - " + e);
           }
         } else {
           Log.e(
               TAG,
               String.format(
                   "no enough space for initDiskCache %s %s",
                   FileUtil.getUsableSpace(mDiskCacheDir), mDiskCacheSize));
         }
       }
     }
     mDiskCacheStarting = false;
     mDiskCacheReady = true;
     mDiskCacheLock.notifyAll();
   }
 }
  private FileInputStream read(String fileCacheKey) {
    if (!mDiskCacheReady) {
      initDiskCache();
    }

    synchronized (mDiskCacheLock) {
      while (mDiskCacheStarting) {
        try {
          if (DEBUG) {
            Log.d(TAG, "read wait " + this);
          }
          mDiskCacheLock.wait();
        } catch (InterruptedException e) {
        }
      }
      if (mDiskLruCache != null) {
        InputStream inputStream = null;
        DiskLruCache.Snapshot snapshot = null;
        try {
          snapshot = mDiskLruCache.get(fileCacheKey);

        } catch (final IOException e) {
          Log.e(TAG, "getBitmapFromDiskCache - " + e);
        }

        if (snapshot == null) {
          return null;
        } else {
          inputStream = snapshot.getInputStream(DISK_CACHE_INDEX);
          return (FileInputStream) inputStream;
        }
      }
      return null;
    }
  }
 @Override
 public long getUsedSpace() {
   if (null == mDiskLruCache) {
     return 0;
   }
   return mDiskLruCache.size();
 }
 /**
  * Closes the disk cache associated with this ImageProvider object. Note that this includes disk
  * access so this should not be executed on the main/UI thread.
  */
 public void closeDiskCache() {
   synchronized (mDiskCacheLock) {
     if (mDiskLruCache != null) {
       try {
         if (!mDiskLruCache.isClosed()) {
           mDiskLruCache.close();
           mDiskLruCache = null;
           if (DEBUG) {
             Log.d(TAG, "Disk cache closed");
           }
         }
       } catch (IOException e) {
         Log.e(TAG, "close - " + e);
       }
     }
   }
 }
 public Editor open(String key) throws IOException {
   if (null != mDiskLruCache) {
     return mDiskLruCache.edit(key);
   } else {
     Log.e(TAG, "mDiskLruCache is null");
     return null;
   }
 }
  /**
   * Clears both the memory and disk cache associated with this ImageProvider object. Note that this
   * includes disk access so this should not be executed on the main/UI thread.
   */
  public void clearCache() {

    synchronized (mDiskCacheLock) {
      mDiskCacheStarting = true;
      mDiskCacheReady = false;

      if (mDiskLruCache != null && !mDiskLruCache.isClosed()) {
        try {
          mDiskLruCache.delete();
          if (DEBUG) {
            Log.d(TAG, "Disk cache cleared");
          }
        } catch (IOException e) {
          e.printStackTrace();
          Log.e(TAG, "clearCache - " + e);
        }
        mDiskLruCache = null;

        initDiskCache();
      }
    }
  }
  /**
   * Adds a bitmap to both memory and disk cache
   *
   * @param key Unique identifier for the bitmap to store
   * @param bitmap The bitmap to store
   */
  public void write(String key, Bitmap bitmap) {
    if (key == null || bitmap == null) {
      return;
    }

    synchronized (mDiskCacheLock) {

      // Add to disk cache
      if (mDiskLruCache != null) {
        OutputStream out = null;
        try {
          DiskLruCache.Snapshot snapshot = mDiskLruCache.get(key);
          if (snapshot == null) {
            final DiskLruCache.Editor editor = mDiskLruCache.edit(key);
            if (editor != null) {
              out = editor.newOutputStream(DISK_CACHE_INDEX);
              bitmap.compress(DEFAULT_COMPRESS_FORMAT, DEFAULT_COMPRESS_QUALITY, out);
              editor.commit();
              out.close();
            }
          }
        } catch (final IOException e) {
          Log.e(TAG, "addBitmapToCache - " + e);
        } catch (Exception e) {
          Log.e(TAG, "addBitmapToCache - " + e);
        } finally {
          try {
            if (out != null) {
              out.close();
            }
          } catch (IOException e) {
          }
        }
      }
    }
  }
 /**
  * Flushes the disk cache associated with this ImageProvider object. Note that this includes disk
  * access so this should not be executed on the main/UI thread.
  */
 public void flushDiskCache() {
   synchronized (mDiskCacheLock) {
     long now = System.currentTimeMillis();
     if (now - 1000 < mLastFlushTime) {
       return;
     }
     mLastFlushTime = now;
     if (mDiskLruCache != null) {
       try {
         mDiskLruCache.flush();
         if (DEBUG) {
           Log.d(TAG, "Disk cache flushed");
         }
       } catch (IOException e) {
         Log.e(TAG, "flush - " + e);
       }
     }
   }
 }