歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Android內存優化之內存緩存

前言:

上面兩篇文章已經講了圖片的基本知識和圖片的加載方法及優化,所有的這些優化都是為了避免應用出現OOM這個問題。一個好的應用程序不僅要健壯不能出錯還要方便用戶使用,對於用戶來說你的應用不僅要美觀還要流暢,很快的呈現給他想要的。很快的加載圖片除了加載的優化外還需要緩存,下面這篇文章將會講圖片緩存。

什麼是緩存?

緩存技術原理就是把用戶訪問的所有對象看作一個全集,經過算法標記哪些是用戶經常訪問的對象,把這些對象放到一個集合裡,這個集合是全集一個子集,下一次用戶再訪問的時候會先從這個子集集合中查找用戶要訪問的對象如果找到就直接返回這個對象,如果沒有找到則再去全集中查找。當然了我這裡說的只是原理性的東西,緩存是有很多算法的,並且有的不止一級緩存,這裡就不過多講了。

為什麼要用到緩存?

有緩存的話可以不必每次從源地址讀取文件,既節省了時間也節省了流量。尤其是手機設備,頻繁的訪問網絡資源會消耗很多用戶的流量和電量,這是用戶不能忍受的,所以無論從哪個方面考慮應用程序都必須加上緩存。

Android中的圖片緩存有哪些?各有什麼特點?

Android設備的圖片緩存分兩種,一種是內存緩存,圖片緩存在設備的內存中,一種是外部緩存,圖片緩存在磁盤上,磁盤可以是內部的存儲空間也可以是外部的sd卡。這兩種緩存各有各的優點,內存緩存優點是快,缺點是因為也是讀取到內存中所以也會消耗內存,所以不能太大,用的時候要考慮分配的空間,還有一個缺點是應用重啟後就會消失。外部緩存的優點是可以長久保存大量的數據(相比較內存緩存而言),缺點就是慢。

內存緩存:

在Android中官網推薦使用LruCache作為內存緩存,LruCache實際上就是一個LinkedHashMap( 補充知識:LinkedHashMap是一個雙向循環列表,不支持線程安全,LruCache對它進行了封裝添加了線程安全操作),裡面保存了一定數量的對象強引用,每次添加的新對象都是在鏈表的頭,當分配的空間用完的時候會把末尾的對象移除,移除的對象就可以被gc回收了。這裡需要注意一下LruCache的容量,這個容量既不能太大,會造成OOM,又不能太小,起不到緩存的作用。google官網給出一下意見作為參考:

  • 分配LruCache大小的時候考慮你的應用剩余內存有多大;
  • 一次屏幕顯示多少張圖片,有多少張圖片是緩存起來准備顯示的;
  • 考慮你的手機分辨率和尺寸, 緩存相同的圖片個數,dpi越大的手機需要的內存就會越大,我的一篇博客中有講解;
  • 圖片分辨率和像素質量也決定了占用內存的大小;
  • 圖片訪問的頻繁程度是多少,是不是有一些圖片是經常訪問的?如果存在你可以考慮用多個LruCache來做緩存,按照訪問的頻率度分配到不同的LruCache中;
  • 如何平衡一下圖片質量和數量,有些時候可以考慮緩存低分辨率的圖片,用到的時候再在後台請求更高質量的圖片;

總之你分配的LruCache大小既不能太大,又不能太小,具體到應用中還要你綜合考慮。

下面的代碼是使用LruCache的例子:

private LruCache<String, Bitmap> mMemoryCache;//聲明緩存空間
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);//獲取應用在系統中的最大內存分配
//分配1/8的應用內存作為緩存空間
final int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
    @Override
      protected int sizeOf(String key, Bitmap bitmap) {
            //重寫sizeOf方法,返回圖片的占用字節數而不是圖片的個數,每次添加圖片是會被調用
          return bitmap.getByteCount() / 1024;
        }
};

注意:有同學可能會問下面的代碼:

  int cacheSize = 4 * 1024 * 1024; // 4MiB
  LruCache bitmapCache = new LruCache(cacheSize) {
      protected int sizeOf(String key, Bitmap value) {
          return value.getByteCount();
  }
}

這兩個sizeOf的計算是不一樣的,這裡說明一下,這個方法重寫的目的是返回圖片占用的緩存空間而不是圖片的數目,並且這個數值的單位要和cacheSize一樣。

總結:

綜合上面的講解,在使用內存緩存LruCache時你需要知道如下知識:

  • LruCache封裝了LinkedHashMap,提供了LRU(Least Recently Used 最近最少使用算法)緩存的功能;
  • LruCache通過trimToSize方法自動刪除最近最少訪問的鍵值對;
  • LruCache不允許空鍵值, LinkedHashMap允許;
  • LruCache線程安全, LinkedHashMap線程不安全;
  • 繼承LruCache時,必須要復寫sizeOf方法,用於計算每個條目的大小。在put和get的時候會調用safeSizeOf(K key, V value),safeSizeOf(K key, V value)會調用 sizeOf (K key, V value),這個方法默認返回1。

下一篇文章將會介紹磁盤緩存。

更多Android相關信息見Android 專題頁面 http://www.linuxidc.com/topicnews.aspx?tid=11

Copyright © Linux教程網 All Rights Reserved