1. 程式人生 > >不積跬步,無以至千里,不積小流,無以成江海

不積跬步,無以至千里,不積小流,無以成江海

我們在開發中用了許多載入圖片的框架都封裝了快取機制,圖片的三級快取的核心類就是LruCache類,嘗試手寫三級快取工具類:

/**
 * 自定義的載入網路圖片工具:三級快取
 * @author wangk
 *
 */
public class MyBitmapUtils {

    private Context context;

    private LruCache<String, Bitmap> lruCache;

    private File rootFile;//本地快取根目錄

    private ExecutorService executorService;

    public
MyBitmapUtils(Context context) { this.context = context; /** * maxSize:lruCache能管理的最大記憶體,此處設定為最大記憶體的1/8 */ int maxSize = (int) (Runtime.getRuntime().maxMemory()/8);//Runtime.getRuntime().maxMemory()當前應用可使用的最大記憶體 lruCache = new LruCache<String, Bitmap>(maxSize){ /** * 當前儲存的物件,bitmap,如何計算大小 */
@Override protected int sizeOf(String key, Bitmap bitmap) { return bitmap.getRowBytes() * bitmap.getHeight();//每一行的位元組個數*高度 = bitmap的大小 } }; //本地快取到data/data rootFile = context.getFilesDir(); executorService = Executors.newFixedThreadPool(3
);//建立固定大小的執行緒池,內部維護了3個執行緒 } /** * 展示網路圖片 * @param image : 展示的空間 * @param imageUrl: 圖片的url */ public void display(ImageView image, String imageUrl) { /** * 三級快取 (圖片) * 1.記憶體快取 HashMap <key,value> key:圖片url,value:bitmap * v4:LruCache 類似hashmap <key,value> lru演算法:less recent use,最少最近使用 * 2.本地快取 儲存sd卡,mnt/sdcard/zhbj_10/image/xxx.png * xxx:圖片名稱,一般以圖片的 url+md5 命名 * url:唯一,還能通過url獲取本地快取圖片 * md5加密:為了避免url的特殊字元 * 3.網路快取 * * 使用步驟: 遵循原則:優先獲取載入速度最快的快取資料 * 1.從記憶體中獲取,如果獲取到圖片,直接展示。如果獲取不到,從本地快取獲取 * 2.從本地快取中獲取,如果獲取到圖片,先載入到記憶體,然後展示。如果獲取不到,從網路獲取 * 3.從網路獲取,如果獲取到圖片,載入到記憶體中,然後展示,儲存到本地。 */ //1.從記憶體中獲取圖片 Bitmap cacheBitmap = lruCache.get(imageUrl); if(cacheBitmap!=null){ image.setImageBitmap(cacheBitmap); System.out.println("從記憶體中獲取"); return ; } //2. 從本地獲取 String imageName = MD5Encoder.encode(imageUrl);//url+md5加密 File cacheFile = new File(rootFile, imageName); if(cacheFile.exists() && cacheFile.length()!=0){ //載入到記憶體中,展示 Bitmap decodeFileBitmap = BitmapFactory.decodeFile(cacheFile.getAbsolutePath()); lruCache.put(imageUrl, decodeFileBitmap); image.setImageBitmap(decodeFileBitmap); System.out.println("從本地中獲取"); return; } //3.從網路獲取 int position = (Integer) image.getTag(); executorService.execute(new DownLoadRunnable(image,imageUrl,position)); System.out.println("從網路獲取"); } class DownLoadRunnable implements Runnable{ private ImageView image; private String imageUrl; private int position; /** * * @param image * @param imageUrl * @param position:請求的位置 */ public DownLoadRunnable(ImageView image, String imageUrl, int position) { this.image = image; this.imageUrl = imageUrl; this.position = position; } @Override public void run() { try { SystemClock.sleep(1000); //從網路獲取:HttpUrlConnection獲取網路圖片 URL url = new URL(imageUrl); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); //設定超時時間 httpURLConnection.setConnectTimeout(5*1000); //設定請求方式 httpURLConnection.setRequestMethod("GET"); //獲取響應碼 int responseCode = httpURLConnection.getResponseCode(); if(responseCode == 200){//請求成功 InputStream inputStream = httpURLConnection.getInputStream(); final Bitmap decodeStreamBitmap = BitmapFactory.decodeStream(inputStream); //儲存到記憶體 lruCache.put(imageUrl, decodeStreamBitmap); //儲存到本地(bitmap物件如何轉換成本地檔案) /** * compress:壓縮 * format:壓縮格式:png、jgp * quality:壓縮質量:0-100,0-完全壓縮,100-不壓縮 * outputStream:輸出流,寫到本地 */ File cacheFile = new File(rootFile, MD5Encoder.encode(imageUrl)); OutputStream ops = new FileOutputStream(cacheFile); decodeStreamBitmap.compress(CompressFormat.PNG, 100, ops); //展示 MainActivity mainActivity = (MainActivity) context; mainActivity.runOnUiThread(new Runnable()//Runnable在子執行緒還是主執行緒中執行,主要看呼叫者 { @Override public void run() { int currentPosition = (Integer) image.getTag(); //請求的位置如果是當前顯示在螢幕上的位置 if(position == currentPosition){ image.setImageBitmap(decodeStreamBitmap); } } }); } } catch (Exception e) { e.printStackTrace(); } } } }