2013-08-26 13 views
11

Hier ist das Disketten-Cache-Tutorial, dem ich folge. Ich habe den Quellcode auf DiskLruCache heruntergeladen, aber keine der in diesem Beispiel verwendeten Methoden existiert im Quellcode.DiskLruCache von Android Tutorial fehlt viele Methoden.

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html#disk-cache

Muss ich diese Methoden selbst implementieren müssen, oder gibt es eine Version von DiskLruCache, die ich irgendwo bin fehlt?

+1

https://code.google.com/p/android/issues/attachmentText?id=29400&aid=294000000000&name=DiskLruCache.java&token=Rstp2OFViiWaUGS68yFfFgMQDEk%3A1335231242264 –

+1

Haben auch Sie die richtige DiskLruCache.java? Vielleicht kann diese Arbeit: https://developer.android.com/samples/DisplayingBitmaps/src/com.example.android.displayingbitmaps/util/DiskLruCache.html –

+0

[issuetracker.google.com/issues/37002468](https:/ /issuetracker.google.com/issues/37002468) – rraallvv

Antwort

2

Hier ist die vollständige Implementierung von DiskLruCache.

Erster Download DiskLruCache.java von AOSP.

Hier ist meine DiskCache.java eine Hilfsklasse für grundlegende Cache-Operationen.

/** 
* Created by Babar on 12-Aug-15. 
*/ 
public class DiskCache 
{ 

    private Context context; 

    private static DiskCache diskCache; 

    public DiskLruCache mDiskLruCache; 

    private final Object mDiskCacheLock = new Object(); 

    private BitmapProcessor bitmapProcessor; 

    private static final int DISK_CACHE_INDEX = 0; 

    public static boolean mDiskCacheStarting = true; 

    private static final String DISK_CACHE_SUBDIR = "ooredoo_thumbnails"; 

    private static final int DISK_CACHE_SIZE = 1024 * 1024 * 100; // 100MB 

    public static DiskCache getInstance() 
    { 
     if(diskCache == null) 
     { 
      diskCache = new DiskCache(); 
     } 

     return diskCache; 
    } 

    private DiskCache() {} 

    public void requestInit(Context context) 
    { 
     this.context = context; 

     bitmapProcessor = new BitmapProcessor(); 

     new DiskCacheTask(this).execute(DiskCacheTask.INIT); 
    } 

    public void init() throws IOException { 
     synchronized (mDiskCacheLock) 
     { 
      if(mDiskLruCache == null || mDiskLruCache.isClosed()) 
      { 
       File cacheDir = FileUtils.getDiskCacheDir(context, DISK_CACHE_SUBDIR); 

       if(!cacheDir.exists()) 
       { 
        cacheDir.mkdir(); 
       } 

       if(FileUtils.getUsableSpace(cacheDir) > DISK_CACHE_SIZE) 
       { 
        mDiskLruCache = DiskLruCache.open(cacheDir, 1, 1, DISK_CACHE_SIZE); 
       } 
       else 
       { 
        Logger.print("InitDiskCache failed: NOT enough space on disk"); 
       } 
      } 

      mDiskCacheStarting = false; // Finished initialization 
      mDiskCacheLock.notifyAll(); // Wake any waiting threads 
     } 
    } 


    public void addBitmapToDiskCache(final String key, final Bitmap value) { 
     if (key == null || value == null) { 
      return; 
     } 

     synchronized (mDiskCacheLock) 
     { 
      if (mDiskLruCache != null) { 
       OutputStream out = null; 

       String encryptedKey = CryptoUtils.encryptToMD5(key); 

       Logger.print("addBitmapToDiskCache encryptToMD5: " + encryptedKey); 

       try { 
        DiskLruCache.Snapshot snapshot = mDiskLruCache.get(encryptedKey); 

        if (snapshot == null) { 
         final DiskLruCache.Editor editor = mDiskLruCache.edit(encryptedKey); 

         if (editor != null) { 
          out = editor.newOutputStream(DISK_CACHE_INDEX); 

          value.compress(Bitmap.CompressFormat.JPEG, 100, out); 

          editor.commit(); 
          out.close(); 
         } 
        } else { 
         snapshot.getInputStream(DISK_CACHE_INDEX).close(); 
        } 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } finally { 
        if (out != null) { 
         try { 
          out.close(); 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      } 
     } 
    } 

    /** 
    * Get from disk cache. 
    * 
    * @param key Unique identifier for which item to get 
    * @return The bitmap if found in cache, null otherwise 
    */ 
    public Bitmap getBitmapFromDiskCache(final String key) 
    { 
     Bitmap bitmap = null; 

     String encryptedKey = CryptoUtils.encryptToMD5(key); 

     Logger.print("getBitmapFromDiskCache encryptToMD5: " + encryptedKey); 

     synchronized (mDiskCacheLock) 
     { 
      Logger.print("mDiskcachestarting: "+mDiskCacheStarting); 
      // Wait while disk cache is started from background thread 
      while (mDiskCacheStarting) 
      { 
       try 
       { 
        mDiskCacheLock.wait(); 
       } 
       catch (InterruptedException e) 
       { 
        e.printStackTrace(); 
       } 
      } 

      if(mDiskLruCache != null) 
      { 
       InputStream inputStream = null; 

       try 
       { 
        final DiskLruCache.Snapshot snapshot = mDiskLruCache.get(encryptedKey); 

        if(snapshot != null) 
        { 
         Logger.print("Disk cache hit"); 

         inputStream = snapshot.getInputStream(DISK_CACHE_INDEX); 

         if(inputStream != null) 
         { 
          FileDescriptor fd = ((FileInputStream) inputStream).getFD(); 

          // Decode bitmap, but we don't want to sample so give 
          // MAX_VALUE as the target dimensions 

          bitmap = bitmapProcessor.decodeSampledBitmapFromDescriptor(fd); 
         } 
        } 
       } 
       catch (IOException e) 
       { 
        e.printStackTrace(); 
       } 
       finally 
       { 
        if(inputStream != null) 
        { 
         try 
         { 
          inputStream.close(); 
         } 
         catch (IOException e) 
         { 
          e.printStackTrace(); 
         } 
        } 
       } 
      } 
      Logger.print("dCache getBitmapFromDiskCache synchronized completed"); 
     } 

     Logger.print("dCache getBitmapFromDiskCache returning Bitmap"); 
     return bitmap; 
    } 

    public void requestFlush() 
    { 
     new DiskCacheTask(this).execute(DiskCacheTask.FLUSH); 
    } 

    /** 
    * Flushes the disk cache associated with this ImageCache object. Note that this includes 
    * disk access so this should not be executed on the main/UI thread. 
    */ 
    public void flush() 
    { 
     synchronized (mDiskCacheLock) 
     { 
      if(mDiskLruCache != null) 
      { 
       try 
       { 
        mDiskLruCache.flush(); 

        Logger.print("flush: disk cache flushed"); 
       } 
       catch (IOException e) 
       { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

    public void requestClose() 
    { 
     new DiskCacheTask(this).execute(DiskCacheTask.CLOSE); 
    } 

    /** 
    * Closes the disk cache associated with this ImageCache object. Note that this includes 
    * disk access so this should not be executed on the main/UI thread. 
    */ 
    public void close() 
    { 
     synchronized (mDiskCacheLock) 
     { 
      if(mDiskLruCache != null) 
      { 
       if(!mDiskLruCache.isClosed()) 
       { 
        try 
        { 
         mDiskLruCache.close(); 
         mDiskLruCache = null; 

         Logger.print("disk cache closed"); 
        } 
        catch (IOException e) 
        { 
         e.printStackTrace(); 
        } 
       } 
      } 
     } 
    } 

    /** 
    * Do not call this method unless you need to explicitly clear disk cache 
    */ 
    public void requestTearDown() 
    { 
     new DiskCacheTask(this).execute(DiskCacheTask.TEAR_DOWN); 
    } 

    public final void tearDown() 
    { 
     synchronized (mDiskCacheLock) 
     { 
      mDiskCacheStarting = true; 

      if(mDiskLruCache != null && !mDiskLruCache.isClosed()) 
      { 
       try 
       { 
        mDiskLruCache.delete(); 

        Logger.print("disk cache cleared"); 
       } 
       catch (IOException e) 
       { 
        e.printStackTrace(); 
       } 

       mDiskLruCache = null; 
      } 
     } 
    } 
} 

Hier ist BitmapProcesser.java

/** 
* @author Babar 
* @since 15-Jun-15. 
*/ 
public class BitmapProcessor 
{ 
    public Bitmap decodeSampledBitmapFromStream(InputStream inputStream, URL url, 
               int reqWidth, int reqHeight) throws IOException { 
     Bitmap bitmap; 

     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 

     BitmapFactory.decodeStream(inputStream, null, options); 

     int width = options.outWidth; 
     int height = options.outHeight; 

     Logger.print("@Req Width: "+reqWidth); 
     Logger.print("@Req Height: " + reqHeight); 

     Logger.print("@Actual Width: "+width); 
     Logger.print("@Actual Height: " + height); 

     int sampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

     options.inJustDecodeBounds = false; 
     options.inSampleSize = sampleSize; 

     inputStream = url.openStream(); 

     bitmap = BitmapFactory.decodeStream(inputStream, null, options); 

     if(bitmap != null) 
     { 
      width = bitmap.getWidth(); 
      height = bitmap.getHeight(); 

      Logger.print("@inSample:"+sampleSize); 
      Logger.print("@Modified Width: "+width); 
      Logger.print("@Modified Height: " + height); 
     } 

     return bitmap; 
    } 

    public Bitmap decodeSampledBitmapFromDescriptor(FileDescriptor fd) 
    { 
     /*final BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 

     BitmapFactory.decodeFileDescriptor(fd, null, options); 

     options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

     options.inJustDecodeBounds = false;*/ 

     return BitmapFactory.decodeFileDescriptor(fd); 

    } 

    public Bitmap decodeSampledBitmapFromFile(String pathName, int reqWidth, int reqHeight) throws IOException { 
     Bitmap bitmap; 

     BitmapFactory.Options options = new BitmapFactory.Options(); 
     options.inJustDecodeBounds = true; 

     BitmapFactory.decodeFile(pathName, options); 

     int width = options.outWidth; 
     int height = options.outHeight; 

     Logger.print("@Req Width: "+reqWidth); 
     Logger.print("@Req Height: " + reqHeight); 

     Logger.print("@Actual Width: "+width); 
     Logger.print("@Actual Height: " + height); 

     int sampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

     options.inJustDecodeBounds = false; 
     options.inSampleSize = sampleSize; 

     bitmap = BitmapFactory.decodeFile(pathName, options); 

     if(bitmap != null) 
     { 
      width = bitmap.getWidth(); 
      height = bitmap.getHeight(); 

      Logger.print("@inSample:"+sampleSize); 
      Logger.print("@Modified Width: "+width); 
      Logger.print("@Modified Height: " + height); 
     } 

     return bitmap != null ? rotateBitmapIfNeeded(pathName, bitmap) : null; 
    } 

    public int calculateInSampleSize(BitmapFactory.Options options, 
            int requiredWidth, int requiredHeight) 
    { 
     final int width = options.outWidth; 
     final int height = options.outHeight; 

     int inSampleSize = 1; 

     if(width > requiredWidth || height > requiredHeight) 
     { 
      final int halfWidth = width/2; 
      final int halfHeight = height/2; 

      // Calculate the largest inSampleSize value that is a power of 2 and keeps both 
      // height and width larger than the requested height and width. 
      while ((halfWidth/inSampleSize) > requiredWidth 
            && 
        (halfHeight/inSampleSize) > requiredHeight) 
      { 
       inSampleSize *= 2; 
      } 
     } 

     return inSampleSize; 
    } 

    public static Bitmap rotateBitmapIfNeeded(String pathName, Bitmap bitmap) throws IOException { 
     ExifInterface exifInterface = new ExifInterface(pathName); 

     int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, 
                 ExifInterface.ORIENTATION_NORMAL); 

     Logger.logI("BITMAP_ORIENTATION: " + orientation, pathName); 

     switch (orientation) 
     { 
      case ExifInterface.ORIENTATION_ROTATE_90: 

       return rotateBitmap(bitmap, 90); 

      case ExifInterface.ORIENTATION_ROTATE_180: 

       return rotateBitmap(bitmap, 180); 

      case ExifInterface.ORIENTATION_ROTATE_270: 

       return rotateBitmap(bitmap, 270); 
     } 

     return bitmap; 
    } 

    public Bitmap makeBitmapRound(Bitmap src) 
    { 
     int width = src.getWidth(); 
     int height = src.getHeight(); 

     Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 

     // Canvas canvas = new Canvas(bitmap); 

     BitmapShader shader = new BitmapShader(src, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 

     Paint paint = new Paint(); 
     paint.setAntiAlias(true); 
     paint.setShader(shader); 



     RectF rectF = new RectF(0.0f, 0.0f, width, height); 

     // rect contains the bounds of the shape 
     // radius is the radius in pixels of the rounded corners 
     // paint contains the shader that will texture the shape 

     Canvas canvas = new Canvas(src); 

     canvas.drawRoundRect(rectF, 30, 30, paint); 

     return src; 
    } 

    public static Bitmap rotateBitmap(Bitmap bitmap, int degree) { 
     Matrix matrix = new Matrix(); 
     matrix.postRotate(degree); 

     return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); 
    } 
} 

Hier ist CryptoUtils.java

/** 
* @author Babar 
* @since 29-Jun-15. 
*/ 
public class CryptoUtils 
{ 
    private static final String MD5_ALGO = "MD5"; 


    public static String encryptToMD5(String text) 
    { 
     try 
     { 
      java.security.MessageDigest md = java.security.MessageDigest.getInstance(MD5_ALGO); 
      md.update(text.getBytes()); 

      byte[] bytes = md.digest(); 

      String hex = bytesToHexString(bytes); 

      return hex; 
     } 
     catch (NoSuchAlgorithmException e) 
     { 
      e.printStackTrace(); 

      return String.valueOf(text.hashCode()); 
     } 
    } 

    private static String bytesToHexString(byte[] bytes) 
    { 
     StringBuffer sb = new StringBuffer(); 

     for(int i = 0; i < bytes.length; i++) 
     { 
      String hex = Integer.toHexString(0xFF & bytes[i]); 

      if(hex.length() == 1) 
      { 
       sb.append('0'); 
      } 

      sb.append(hex); 
     } 

     return sb.toString(); 
    } 

    public static String encodeToBase64(String str) { 
     String tmp = ""; 
     if(isNotNullOrEmpty(str)) { 
      try { 
       tmp = new String(Base64.encode(str.getBytes(), Base64.DEFAULT)).trim(); 
      } catch(Throwable e) { 
       e.printStackTrace(); 
      } 
     } 
     return tmp; 
    } 
} 

Hier ist DiskCacheTask.java

/** 
* Created by Babar on 12-Aug-15. 
*/ 
public class DiskCacheTask extends BaseAsyncTask<Integer, Void, Void> 
{ 
    private DiskCache diskCache; 

    public static final int INIT = 1; 

    public static final int FLUSH = 2; 

    public static final int CLOSE = 3; 

    public static final int TEAR_DOWN = 4; 

    public static final int REMOVE = 5; 

    public DiskCacheTask(DiskCache diskCache) 
    { 
     this.diskCache = diskCache; 
    } 

    @Override 
    protected Void doInBackground(Integer... params) 
    { 
     switch (params[0]) 
     { 
      case INIT: 

       try 
       { 
        diskCache.init(); 
       } 
       catch (IOException e) 
       { 
        e.printStackTrace(); 
       } 

       break; 

      case FLUSH: 

       diskCache.flush(); 

       break; 

      case CLOSE: 

       diskCache.close(); 

       break; 

      case TEAR_DOWN: 

       diskCache.tearDown(); 

       break; 

      case REMOVE: 

       diskCache.remove(); 

       break; 
     } 

     return null; 
    } 
} 

die cac zu initialisieren Er ruft einfach new DiskCache().getInstance().requestInit(); aus der MainActivity onCreate(). Beachten Sie außerdem, dass die Disk-Operation in einem separaten Thread erfolgen sollte, zum Beispiel Handler, AsyncTask. Wann immer Sie also Bitmap zum/vom Plattencache hinzufügen/holen wollen, tun Sie dies von einem Arbeitsthread.