詳解Android 圖片的三級緩衝及圖片壓縮_Android

來源:互聯網
上載者:User

為什麼需要圖片緩衝

Android預設給每個應用只分配16M的記憶體,所以如果載入過多的圖片,為了防止記憶體溢出,應該將圖片緩衝起來。圖片的三級緩衝分別是:

  • 記憶體緩衝
  • 本機快取
  • 網路緩衝

其中,記憶體緩衝應優先載入,它速度最快;本機快取次優先載入,它速度也快;網路緩衝不應該優先載入,它走網路,速度慢且耗流量。

三級緩衝的具體實現

網路緩衝

  • 根據圖片的url去載入圖片
  • 在本地和記憶體中緩衝

  

 public class NetCacheUtils {    private LocalCacheUtils mLocalCacheUtils;    private MemoryCacheUtils mMemoryCacheUtils;    public NetCacheUtils(LocalCacheUtils localCacheUtils,        MemoryCacheUtils memoryCacheUtils) {      mLocalCacheUtils = localCacheUtils;      mMemoryCacheUtils = memoryCacheUtils;    }    /**     * 從網路下載圖片     *      * @param ivPic     * @param url     */    public void getBitmapFromNet(ImageView ivPic, String url) {      new BitmapTask().execute(ivPic, url);// 啟動AsyncTask,                          // 參數會在doInbackground中擷取    }    /**     * Handler和線程池的封裝     *      * 第一個泛型: 參數類型 第二個泛型: 更新進度的泛型, 第三個泛型是onPostExecute的返回結果     *      *      */    class BitmapTask extends AsyncTask<Object, Void, Bitmap> {      private ImageView ivPic;      private String url;      /**       * 後台耗時方法在此執行, 子線程       */      @Override      protected Bitmap doInBackground(Object... params) {        ivPic = (ImageView) params[0];        url = (String) params[1];        ivPic.setTag(url);// 將url和imageview綁定        return downloadBitmap(url);      }      /**       * 更新進度, 主線程       */      @Override      protected void onProgressUpdate(Void... values) {        super.onProgressUpdate(values);      }      /**       * 耗時方法結束後,執行該方法, 主線程       */      @Override      protected void onPostExecute(Bitmap result) {        if (result != null) {          String bindUrl = (String) ivPic.getTag();          if (url.equals(bindUrl)) {// 確保圖片設定給了正確的imageview            ivPic.setImageBitmap(result);            mLocalCacheUtils.setBitmapToLocal(url, result);// 將圖片儲存在本地            mMemoryCacheUtils.setBitmapToMemory(url, result);// 將圖片儲存在記憶體            System.out.println("從網路緩衝讀取圖片啦...");          }        }      }    }    /**     * 下載圖片     *      * @param url     * @return     */    private Bitmap downloadBitmap(String url) {      HttpURLConnection conn = null;      try {        conn = (HttpURLConnection) new URL(url).openConnection();        conn.setConnectTimeout(5000);        conn.setReadTimeout(5000);        conn.setRequestMethod("GET");        conn.connect();        int responseCode = conn.getResponseCode();        if (responseCode == 200) {          InputStream inputStream = conn.getInputStream();          //圖片壓縮處理          BitmapFactory.Options option = new BitmapFactory.Options();          option.inSampleSize = 2;//寬高都壓縮為原來的二分之一, 此參數需要根據圖片要展示的大小來確定          option.inPreferredConfig = Bitmap.Config.RGB_565;//設定圖片格式          Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);          return bitmap;        }      } catch (Exception e) {        e.printStackTrace();      } finally {        conn.disconnect();      }      return null;    }  }

本機快取

兩個方法:設定本機快取,擷取本機快取

  public class LocalCacheUtils {    public static final String CACHE_PATH = Environment        .getExternalStorageDirectory().getAbsolutePath() + "/local_cache";    /**     * 從本地sdcard讀圖片     */    public Bitmap getBitmapFromLocal(String url) {      try {        String fileName = MD5Encoder.encode(url);        File file = new File(CACHE_PATH, fileName);        if (file.exists()) {          Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(              file));          return bitmap;        }      } catch (Exception e) {        e.printStackTrace();      }      return null;    }    /**     * 向sdcard寫圖片     *      * @param url     * @param bitmap     */    public void setBitmapToLocal(String url, Bitmap bitmap) {      try {        String fileName = MD5Encoder.encode(url);        File file = new File(CACHE_PATH, fileName);        File parentFile = file.getParentFile();        if (!parentFile.exists()) {// 如果檔案夾不存在, 建立檔案夾          parentFile.mkdirs();        }        // 將圖片儲存在本地        bitmap.compress(CompressFormat.JPEG, 100,            new FileOutputStream(file));      } catch (Exception e) {        e.printStackTrace();      }    }  }

記憶體緩衝

兩個方法:設定記憶體緩衝,擷取記憶體緩衝

問題:

如果使用HashMap儲存圖片時,當圖片越來越多時,會導致記憶體溢出,因為它是強引用,java的記憶體回收行程不會回收。

如若改成軟引用SoftReference(記憶體不夠時,記憶體回收行程會考慮回收),仍有一個問題:在android2.3+, 系統會優先將SoftReference的對象提前回收掉, 即使記憶體夠用。

解決辦法:可以用LruCache來解決上述記憶體不回收或提前回收的問題。least recentlly use 最少最近使用演算法 它會將記憶體控制在一定的大小內, 超出最大值時會自動回收, 這個最大值開發人員自己定
 

    public class MemoryCacheUtils {      // private HashMap<String, SoftReference<Bitmap>> mMemoryCache = new      // HashMap<String, SoftReference<Bitmap>>();      private LruCache<String, Bitmap> mMemoryCache;      public MemoryCacheUtils() {        long maxMemory = Runtime.getRuntime().maxMemory() / 8;// 模擬器預設是16M        mMemoryCache = new LruCache<String, Bitmap>((int) maxMemory) {          @Override          protected int sizeOf(String key, Bitmap value) {            int byteCount = value.getRowBytes() * value.getHeight();// 擷取圖片佔用記憶體大小            return byteCount;          }        };      }      /**       * 從記憶體讀       *        * @param url       */      public Bitmap getBitmapFromMemory(String url) {        // SoftReference<Bitmap> softReference = mMemoryCache.get(url);        // if (softReference != null) {        // Bitmap bitmap = softReference.get();        // return bitmap;        // }        return mMemoryCache.get(url);      }      /**       * 寫記憶體       *        * @param url       * @param bitmap       */      public void setBitmapToMemory(String url, Bitmap bitmap) {        // SoftReference<Bitmap> softReference = new        // SoftReference<Bitmap>(bitmap);        // mMemoryCache.put(url, softReference);        mMemoryCache.put(url, bitmap);      }    }

圖片壓縮

  //圖片壓縮處理(在從網路擷取圖片的時候就進行壓縮)  BitmapFactory.Options option = new BitmapFactory.Options();  option.inSampleSize = 2;//寬高都壓縮為原來的二分之一, 此參數需要根據圖片要展示的大小來確定  option.inPreferredConfig = Bitmap.Config.RGB_565;//設定圖片格式  Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, option);

以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援雲棲社區。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.