中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android Bitmap的加載與緩存

發布時間:2020-09-30 16:23:08 來源:腳本之家 閱讀:108 作者:mmmmar 欄目:移動開發

Android系統中圖片一般用Bitmap對象表示,它支持png,jpg等常見格式。通常情況下圖片的體積都比較大,單個應用允許使用的內存又是有限的,所以我們需要采取一些手段減少內存占用并提高加載速度。

1、圖片加載

SDK提供了BitmapFactory類供我們加載圖片,常用的方法有這么幾個:

  •  BitmapFactory.decodeFile :從文件加載。
  •  BitmapFactory.decodeByteArray :從字節數組加載。
  •  BitmapFactory.decodeStream :從輸入流加載。
  •  BitmapFactory.decodeResource :從資源文件加載。

假設我們用ImageView顯示圖片,通常它的尺寸要比圖片的尺寸小很多,那么把圖片整個加載進內存顯然是沒有必要的。在圖形學上有個名詞叫“下采樣”,作用就是降低圖像的分辨率,使其符合顯示區域的大小。通過BitmapFactory.Options類,我們也可以實現同樣的功能。這里主要用到了它的 inSampleSize 參數,如果它的值是1,那么采樣后的圖片跟原圖一致,如果是2,那么采樣后的圖片長和寬都是原來的一半,占用的內存也就是原來的四分之一。

public static Bitmap decodeSampleBitmapFromBytes(byte[] data) {
  final BitmapFactory.Options options = new BitmapFactory.Options();
  // inJustDecodeBounds為true時僅解析圖片原始信息,并不會真正加載圖片。
  options.inJustDecodeBounds = true;
  BitmapFactory.decodeByteArray(data, 0, data.length, options);
  // 此時圖片的寬高可以通過options.outWidth和options.outHeight獲取到,我們
  // 可以根據自己的需求計算出采樣比。
  options.inSampleSize = 1;
  // inJustDecodeBounds設置為fales,加載圖片到內存中。
  options.inJustDecodeBounds = false;
  return BitmapFactory.decodeResource(res, resId, options);
}

2、圖片緩存

緩存在計算機領域使用非常廣泛,如HTTP緩存,DNS緩存等等,緩存既可以提高響應速度,又能節省服務器帶寬,在圖片加載上它同樣適用。Android開發中一般會對圖片做兩級緩存:內存緩存和文件緩存,而且它們都有庫供我們使用,分別是LruCache和DiskLruCache。從名字就可以看出兩者都使用了LRU算法,即優先淘汰那些近期最少使用的緩存。

2.1、LruCache

LruCache是Android提供的一個緩存類,一般用來管理內存緩存。

// #1:確定緩存大小。
int maxMemory = (int)(Runtime.getRuntime().totalMemory() / 1024);
int cacheSize = maxMemory / 8;
// #2:重寫sizeOf方法計算每個緩存對象的內存占用。
LruCache<String, Bitmap> mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
  @Override
  protected int sizeOf(String key, Bitmap value) {
    return value.getByteCount();
  }
};

LruCache是一個泛型類可以容納各種對象,因而它無法計算被儲存對象的大小,所以我們需要重寫它的 sizeOf 方法,手動進行計算。那LruCache是如何實現的呢,實際上它僅僅是對LinkedHashMap進行了封裝并處理了線程安全問題。LinkedHashMap的構造函數中有一個布爾類型的參數, accessOrder ,當它為 true 時元素按訪問順序存儲,為 false 時按插入順序存儲。當元素按訪問順序存儲時在其尾部取出的元素也就是最近最少使用的元素,也就實現了LRU算法。LruCache只需要每次 put 函數被調用后計算當前總緩存的大小,當其超出門限值時移除位于LinkedHashMap尾部的元素即可。

2.2、DiskLruCache

DiskLruCache同LruCache一樣都使用LinkedHashMap實現LRU算法,但DiskLruCache在實現和使用上更復雜一些,畢竟需要對文件進行管理。

獲得DiskLruCache對象需要調用 DiskLruCache.open 函數:

public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)

它接收4個參數,第一個是緩存區目錄,第二個是客戶端版本號,DiskLruCache認為當版本號發生變化時緩存是無效的,第三個參數代表每個鍵可以關聯幾個文件,最后一個參數指定的緩存區的大小。在創建對象時,DiskLruCache會根據緩沖區目錄下名為“journal”的日志文件在LinkedHashMap中為緩存文件建立索引,所有對緩沖區的操作都會被記錄在這個文件中。當緩沖區大小到達門限值后根據LRU算法對文件進行清理。

讀取緩存時使用 DiskLruCache.get 函數:

public synchronized Snapshot get(String key) throws IOException

函數返回一個Snapshot對象,通過該對象我們可以獲取到緩存文件的輸入流,多個線程可以同時使用各自的SnapShot對象讀取同一個Key對應的緩存。

操作緩存時使用 DiskLruCache.edit 函數:

public Editor edit(String key) throws IOException

創建或更改完畢后用 Editor.commit 函數提交或用 Editor.abort 函數取消。一個Key對應的緩存被操作時仍可以使用Snapshot對象讀取其內容,因為Editor的所有操作都會先作用于臨時文件。注意每個Key只能同時獲取一個Editor對象,也就是說即使Editor沒有做任何操作也要調用 Editor.abort 或  Editor.commit 函數,不然再次獲取時函數返回 null 。

2.3、代碼示例

public Bitmap loadBitmap(String url) {
  // DiskLruCache要求鍵中不能含有特殊字符,所以
  // 一般先做哈希處理。
  String key = MD5(url);
  Bitmap bitmap = loadBitmapFromMemCache(key);
  if (bitmap != null) {
    return bitmap;
  }
  try {
    bitmap = loadBitmapFromDiskCache(key);
    if (bitmap != null) {
      return bitmap;
    }
    bitmap = loadBitmapFromHttp(url);
    if (bitmap != null) {
      return bitmap;
    }
  } catch (IOException e) {
    e.printStackTrace();
  }
  return null;
}

在 loadBitmapFromHttp 函數中需要將圖片資源放入DiskLruCache中,在 loadBitmapFromDiskCache 函數中將加載后的Bitmap對象放入LruCache中,如此便形成了一條緩存鏈。

總結

以上所述是小編給大家介紹的Android Bitmap的加載與緩存,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

沂水县| 拉萨市| 宁津县| 防城港市| 济阳县| 平和县| 泰来县| 清涧县| 海丰县| 饶阳县| 五常市| 巴中市| 六盘水市| 罗源县| 神农架林区| 沙田区| 平远县| 和硕县| 正宁县| 池州市| 张家口市| 天水市| 鄂尔多斯市| 岳池县| 吉水县| 沅江市| 正阳县| 乌兰浩特市| 封丘县| 鄢陵县| 福鼎市| 黑龙江省| 莎车县| 兴业县| 连云港市| 延寿县| 华蓥市| 丰镇市| 阿图什市| 固始县| 榆林市|