Bitmap 學(xué)習(xí)

recycle() 方法

后面會補上

LRU --->LruCache<k,v> 這個類需要看看

進行三級緩存

  • LinkedHashMap<k,v> map ; 保存一個強引用的緩存對象。
  • trimToSize(int maxSize) {} 緩存滿的時候,算法就會移除較早的緩存對象铜靶,然后把新的緩存對象添加到隊列種
  • get() remove()
  • put() 緩存的添加和 獲取操作
    有用到一個entryRemoved() 空方法
 * Caches {@code value} for {@code key}. The value is moved to the head of
 * the queue.
 *
 * @return the previous value mapped by {@code key}.
 */
public final V put(K key, V value) {
    if (key == null || value == null) {
        throw new NullPointerException("key == null || value == null");
    }

    V previous;
    synchronized (this) {
        putCount++;
        size += safeSizeOf(key, value);
        previous = map.put(key, value);
        if (previous != null) {
            size -= safeSizeOf(key, previous);
        }
    }

    if (previous != null) {
        entryRemoved(false, key, previous, value);
    }

    trimToSize(maxSize);
    return previous;
}

以上為 put的方法隘道,有必要復(fù)習(xí)下 synchronized 相關(guān)的操作

synchronized 相關(guān)的 操作

在Java中,synchronized關(guān)鍵字是用來控制線程同步的,就是在多線程的環(huán)境下,控制synchronized代碼段不被多個線程同時執(zhí)行。synchronized既可以加在一段代碼上屏富,也可以加在方法上。
http://blog.csdn.net/xiao__gui/article/details/8188833

synchronized鎖住的是代碼還是對象: synchronized鎖住的是括號里的對象

trimTosize()

 public void trimToSize(int maxSize) {
    while (true) {
        K key;
        V value;
        synchronized (this) {
            if (size < 0 || (map.isEmpty() && size != 0)) {
                throw new IllegalStateException(getClass().getName()
                        + ".sizeOf() is reporting inconsistent results!");
            }

            if (size <= maxSize) {
                break;
            }

            Map.Entry<K, V> toEvict = map.eldest();
            if (toEvict == null) {
                break;
            }

            key = toEvict.getKey();
            value = toEvict.getValue();
            map.remove(key);
            size -= safeSizeOf(key, value);
            evictionCount++;
        }

        entryRemoved(true, key, value, null);
    }
}

這方法是Lru 算法的核心蛙卤,做一個判斷役听,計算剩余的size 有多少,如果只要里面的元素尺寸 小與了他的最大值表窘,為們就會退出循環(huán)典予,不然就會去remove,也就是hashMap的remove乐严, size -= safesizeof(),計算緩存對象的大小瘤袖,最后會掉一個entryremove(),這個方法是個 空方法昂验。如果我們想在lru 算法中做一些二級緩存的話捂敌,可以實現(xiàn)這方法。這就是trimtosize方法既琴,會把最老的最不常用的緩存對象從我們的緩存隊列中移除占婉。

put方法

用的是LinkedHashmap,所以跟正常的map 放入一樣甫恩。 但是 加了:還是同步代碼塊逆济,然后還是計算 size的大小, previous = map.put(key, value); 看看 previous 是否為空,得出新的size大小奖慌。同樣 掉了 entryremove抛虫。

  * Caches {@code value} for {@code 
    key}. The value is moved to the head of
  * the queue.
  *
  * @return the previous value mapped by {@code key}.
   */
 public final V put(K key, V value) {
     if (key == null || value == null) {
        throw new NullPointerException("key == null || value == null");
     }

    V previous;
    synchronized (this) {
        putCount++;
        size += safeSizeOf(key, value);
        previous = map.put(key, value);
        if (previous != null) {
            size -= safeSizeOf(key, previous);
        }
    }

    if (previous != null) {
        entryRemoved(false, key, previous, value);
    }

    trimToSize(maxSize);
    return previous;
}

remove()

 /**
 * Removes the entry for {@code key} if it exists.
 *
 * @return the previous value mapped by {@code key}.
 */
public final V remove(K key) {
    if (key == null) {
        throw new NullPointerException("key == null");
    }

    V previous;
    synchronized (this) {
        previous = map.remove(key);
        if (previous != null) {
            size -= safeSizeOf(key, previous);
        }
    }

    if (previous != null) {
        entryRemoved(false, key, previous, null);
    }

    return previous;
}

計算inSampleSize 的值

bitmap 優(yōu)化,無非就是 合適的時間去加載合適大小的圖片简僧,不可能把每一張原圖大小都加載到內(nèi)存中建椰,所以有個 縮放比,把真實的的 高跟要求的高岛马,做個比例棉姐,返回

// 根據(jù)maxWidth, maxHeight計算最合適的inSampleSize
public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        if (width > height) {
            inSampleSize = Math.round((float)height / (float)reqHeight);
        } else {
            inSampleSize = Math.round((float)width / (float)reqWidth);
        }
    }
    return inSampleSize;
}

縮略圖

根據(jù)insampleSize的值來保存相應(yīng)的bitmap。
有個很重要的屬性啦逆,inJustDecodeBounds.經(jīng)差
 If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.

意思就是說如果該值設(shè)為true那么將不返回實際的bitmap不給其分配內(nèi)存空間而里面只包括一些解碼邊界信息即圖片大小信息伞矩,那么相應(yīng)的方法也就出來了,通過設(shè)置inJustDecodeBounds為true蹦浦,獲取到outHeight(圖片原始高度)和 outWidth(圖片的原始寬度),然后計算一個inSampleSize(縮放值)撞蜂,然后就可以取圖片了盲镶,這里要注意的是,inSampleSize 可能小于0蝌诡,必須做判斷溉贿。也就是說先將Options的屬性inJustDecodeBounds設(shè)為true,先獲取圖片的基本大小信息數(shù)據(jù)(信息沒有保存在bitmap里面浦旱,而是保存在options里面)宇色,通過options.outHeight和 options. outWidth獲取的大小信息以及自己想要到得圖片大小計算出來縮放比例inSampleSize,然后緊接著將inJustDecodeBounds設(shè)為false颁湖,就可以根據(jù)已經(jīng)得到的縮放比例得到自己想要的圖片縮放圖了宣蠕。

   //縮略圖
public static Bitmap thumbnail(String path,
                               int maxWidth, int maxHeight, boolean autoRotate) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    // 獲取這個圖片的寬和高信息到options中, 此時返回bm為空
    Bitmap bitmap = BitmapFactory.decodeFile(path, options);
    options.inJustDecodeBounds = false;
    // 計算縮放比
    int sampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
    options.inSampleSize = sampleSize;
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    options.inPurgeable = true;
    options.inInputShareable = true;
    if (bitmap != null && !bitmap.isRecycled()) {
        bitmap.recycle();
    }
    bitmap = BitmapFactory.decodeFile(path, options);
    return bitmap;
}

三級緩存

  • 網(wǎng)絡(luò)緩存
  • 內(nèi)存緩存
  • 本地緩存

直接走內(nèi)存或者本地緩存,不走流量甥捺。

some code

//保存bitmap
public static String save(Bitmap bitmap,
                           Bitmap.CompressFormat format, int quality, File destFile) {
    try {
        FileOutputStream out = new FileOutputStream(destFile);
        if (bitmap.compress(format, quality, out)) {
            out.flush();
            out.close();
        }
        if (bitmap != null && !bitmap.isRecycled()) {
            bitmap.recycle();
        }
        return destFile.getAbsolutePath();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

and

    // 保存到sd卡
public static String save(Bitmap bitmap,
                           Bitmap.CompressFormat format, int quality, Context context) {
    if (!Environment.getExternalStorageState()
            .equals(Environment.MEDIA_MOUNTED)) {
        return null;
    }
    File dir = new File(Environment.getExternalStorageDirectory()
            + "/" + context.getPackageName() + "/save/");
    if (!dir.exists()) {
        dir.mkdirs();
    }
    File destFile = new File(dir, UUID.randomUUID().toString());
    return save(bitmap, format, quality, destFile);
}

第一次用簡書抢蚀,就是學(xué)的時候記錄一下,到時候自己好查镰禾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末皿曲,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子吴侦,更是在濱河造成了極大的恐慌屋休,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件备韧,死亡現(xiàn)場離奇詭異劫樟,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門毅哗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來听怕,“玉大人,你說我怎么就攤上這事虑绵∧虿t!?“怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵翅睛,是天一觀的道長声搁。 經(jīng)常有香客問我,道長捕发,這世上最難降的妖魔是什么疏旨? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮扎酷,結(jié)果婚禮上檐涝,老公的妹妹穿的比我還像新娘。我一直安慰自己法挨,他們只是感情好谁榜,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凡纳,像睡著了一般窃植。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上荐糜,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天巷怜,我揣著相機與錄音,去河邊找鬼暴氏。 笑死延塑,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的答渔。 我是一名探鬼主播页畦,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼研儒!你這毒婦竟也來了豫缨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤端朵,失蹤者是張志新(化名)和其女友劉穎好芭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冲呢,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡舍败,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邻薯。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡裙戏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出厕诡,到底是詐尸還是另有隱情累榜,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布灵嫌,位于F島的核電站壹罚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏寿羞。R本人自食惡果不足惜猖凛,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绪穆。 院中可真熱鬧辨泳,春花似錦、人聲如沸玖院。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽司恳。三九已至途乃,卻和暖如春绍傲,著一層夾襖步出監(jiān)牢的瞬間扔傅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工烫饼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留猎塞,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓杠纵,卻偏偏與公主長得像荠耽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子比藻,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容