Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android中圖片的三級cache策略(內存、文件、網絡)之三:文件緩存策略

android中圖片的三級cache策略(內存、文件、網絡)之三:文件緩存策略

編輯:關於Android編程

前言

如果想很好地理解下面的故事,請參看我半年前寫的兩篇博文:android中圖片的三級cache策略(內存、文件、網絡) 一 和 android中左右滑屏的實現(廣告位banner組件),還有昨天晚上寫的android中圖片的三級cache策略(內存、文件、網絡)之二:內存緩存策略。

文件緩存策略

當一張圖片從網絡下載成功以後,這個圖片會被加入內存緩存和文件緩存,對於文件緩存來說,這張圖片將被以url的哈希值加cach後綴名的形式存儲在SD卡上,這樣,當下一次再需要同一個url的圖片的時候,就不需要從網絡下載了,而是直接通過url來進行查找。同時一張圖片被訪問時,它的最後修改時間將被更新,這樣的意義在於:當SD卡空間不足的時候,將會按照最後修改時間來刪除40%緩存的圖片,確切來說,那些修改時間比較早的圖片將會被刪除。

代碼展示

public class ImageFileCache
{
    private static final String TAG = "ImageFileCache";
	
    //圖片緩存目錄
    private static final String IMGCACHDIR = "/sdcard/ImgCach";
    
    //保存的cache文件寬展名
    private static final String CACHETAIL = ".cach";
                                                            
    private static final int MB = 1024*1024;
    
    private static final int CACHE_SIZE = 1;
    
    //當SD卡剩余空間小於10M的時候會清理緩存
    private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10;
                                                                
    public ImageFileCache() 
    {
        //清理部分文件緩存
        removeCache(IMGCACHDIR);    		
    }
                                                                
    /** 
     * 從緩存中獲取圖片 
     */
    public Bitmap getImageFromFile(final String url) 
    {    
        final String path = IMGCACHDIR + "/" + convertUrlToFileName(url);
        File file = new File(path);
        if (file != null && file.exists()) 
        {
            Bitmap bmp = BitmapFactory.decodeFile(path);
            if (bmp == null) 
            {
                file.delete();
            } 
            else 
            {
                updateFileTime(path);
                Logger.d(TAG, "get bmp from FileCache,url=" + url);
                return bmp;
            }
        }
        return null;
    }
                                                                
    /**
     * 將圖片存入文件緩存 
     */
    public void saveBitmapToFile(Bitmap bm, String url) 
    {
        if (bm == null) {
            return;
        }
        //判斷sdcard上的空間
        if (FREE_SD_SPACE_NEEDED_TO_CACHE > SdCardFreeSpace()) 
        {
            //SD空間不足
            return;
        }
        
        String filename = convertUrlToFileName(url);
        File dirFile = new File(IMGCACHDIR);
        if (!dirFile.exists())
            dirFile.mkdirs();
        File file = new File(IMGCACHDIR +"/" + filename);
        try 
        {
            file.createNewFile();
            OutputStream outStream = new FileOutputStream(file);
            bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
            outStream.flush();
            outStream.close();
        } 
        catch (FileNotFoundException e) 
        {
            Logger.d(TAG, "FileNotFoundException");
        } 
        catch (IOException e) 
        {
            Logger.d(TAG, "IOException");
        }
    } 
                                                                
    /**
     * 計算存儲目錄下的文件大小,
     * 當文件總大小大於規定的CACHE_SIZE或者sdcard剩余空間小於FREE_SD_SPACE_NEEDED_TO_CACHE的規定
     * 那麼刪除40%最近沒有被使用的文件
     */
    private boolean removeCache(String dirPath) 
    {
        File dir = new File(dirPath);
        File[] files = dir.listFiles();
        
        if (files == null) 
        {
            return true;
        }
        
        if (!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
        {
            return false;
        }
                                                            
        int dirSize = 0;
        for (int i = 0; i < files.length; i++) 
        {
            if (files[i].getName().contains(CACHETAIL)) 
            {
                dirSize += files[i].length();
            }
        }
                                                            
        if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > SdCardFreeSpace()) 
        {
            int removeFactor = (int) (0.4 * files.length);
            Arrays.sort(files, new FileLastModifSort());
            for (int i = 0; i < removeFactor; i++) 
            {
                if (files[i].getName().contains(CACHETAIL)) 
                {
                    files[i].delete();
                }
            }
        }
                                                            
        if (SdCardFreeSpace() <= CACHE_SIZE) 
        {
            return false;
        }
                                                                    
        return true;
    }
                                                                
    /**
     * 修改文件的最後修改時間
     */
    public void updateFileTime(String path) 
    {
        File file = new File(path);
        long newModifiedTime = System.currentTimeMillis();
        file.setLastModified(newModifiedTime);
    }
                                                                
    /** 
     * 計算SD卡上的剩余空間 
     */
    private int SdCardFreeSpace()
    {
        StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
        double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;
        return (int) sdFreeMB;
    } 
                                                                
    /** 
     * 將url轉成文件名 
     */
    private String convertUrlToFileName(String url)
    {
    	return url.hashCode() + CACHETAIL;
    }
                                                                
    /**
     * 根據文件的最後修改時間進行排序
     */
    private class FileLastModifSort implements Comparator 
    {
        public int compare(File file0, File file1) 
        {
            if (file0.lastModified() > file1.lastModified())
            {
                return 1;
            } 
            else if (file0.lastModified() == file1.lastModified()) 
            {
                return 0;
            } 
            else 
            {
                return -1;
            }
        }
    }

}

說明:上述代碼很好理解而且都有注釋,不用多說了。

到這裡,整個banner體系的代碼都被介紹了,希望代碼中的思想能夠對大家有所啟發,謝謝大家的捧場!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved