Bitmap加載與Cache

一,Bitmap的高效加載

  • 如何加載一個圖片?
    BitmapFactiory提供了四個方法:
    decodeFile:從文件系統(tǒng)加載Bitmap對象
    decodeResource:從資源中加載
    decodeStream:通過輸入流加載
    decodeByteArray:通過字節(jié)數(shù)組加載
    其中decodeFile與decodeResource又間接調(diào)用了decodeStream
  • 如何高效的加載Bitmap思路?
    采用BitmapFactory.Options 來加載所需尺寸的圖片,因?yàn)橛械臅r候我們控件所顯示的圖片尺寸沒有圖片那么大,所以可以將其縮小,按照一定的采樣率來加載圖片從而降低內(nèi)存的占用避免OOM统翩。
    通過BitmapFactory.Options來進(jìn)行縮放圖片,主要用到inSampleSize參數(shù)此洲,當(dāng)inSampleSize為1時厂汗,采用后的圖片大小為原始大小,當(dāng)inSampleSize大于時 比如為2時則采用后的圖片寬高均為原來的1/2呜师,像素為原來的1/4娶桦,占有的內(nèi)存大小也為原來的1/4
  • 如何獲取采樣率
    (1)將BitmapFactory.Options的inJustDecodeBounds的參數(shù)設(shè)為true并加載圖片
    (2)從itmapFactory.Options中取出圖片的原始寬高信息
    (3)根據(jù)采樣率的規(guī)則,以及目標(biāo)view展示的大小,計算出采樣率inSampleSize
    (4)將itmapFactory.Options的inJustDecodeBounds參數(shù)設(shè)為false衷畦,重新加載圖片
    注:inJustDecodeBounds設(shè)為true只會解析圖片的寬高信息栗涂,不會真的加載圖片。
 public static Bitmap decodeSampledBitmapFromResource(Resources resources, int resId,
                                                         int reqWidth, int reqHeight) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(resources, resId, options);
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        options.inJustDecodeBounds=false;
        return BitmapFactory.decodeResource(resources, resId, options);
    }

    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        int inSampleSize = 1;
        final int width = options.outWidth;
        final int height = options.outHeight;
        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
            while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }
        return inSampleSize;
    }
mImageView,setImageBitmap(decodeSampledBitmapFromResource(getResources(),R.id.imageview,100,100))

二祈争,Android中的緩存策略

  • LRUCache(線程安全)
    LRU算法:近期最少使用算法
    是一個泛型類斤程,內(nèi)部采用一個LinkedHashMap以強(qiáng)引用的方式存儲外界的緩存對象,提供了get菩混,put的方法來完成緩存的獲取和添加忿墅,當(dāng)緩存滿的時會將較早使用的緩存對象進(jìn)行移除,再添加新的緩存對象沮峡。
    強(qiáng)引用:直接對象的引用
    軟引用:當(dāng)對象只有軟引用存在的時候疚脐,系統(tǒng)內(nèi)存不足時,此對象會隨時被gc回收
    弱引用:當(dāng)對象只有弱引用存在時邢疙,隨時都有可能被GC回收
    LruCache的實(shí)現(xiàn)
    int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
    int cacheSize = maxMemory / 8;
    LruCache<String, Bitmap> lruCache = new LruCache<String, Bitmap>(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap value) {
            return value.getRowBytes()*value.getHeight()/1024;
        }
    };

設(shè)置緩存以及獲取緩存

獲取緩存
mMemoryCache.get(key);
設(shè)置緩存
mMemoryCache.put(key,bitmap);
刪除緩存
mMemoryCache.remove(key);
  • DiskLruCache
    用于實(shí)現(xiàn)存儲設(shè)備的緩存棍弄,即磁盤緩存。通過將緩存對象寫入文件系統(tǒng)從而實(shí)現(xiàn)緩存效果疟游。
    DiskLruCache的創(chuàng)建
public static DiskLruCache open(File directory,int appVersion,int valueCount,long maxSize);

第一個參數(shù):表示磁盤緩存的文件系統(tǒng)中的路徑(可以在SD卡上的緩存目錄照卦,也可以選擇其他位置)
第二個參數(shù):表示應(yīng)用版本號設(shè)置為1即可
第三個參數(shù):設(shè)置為1即可
第四個參數(shù):緩存最大值,當(dāng)超過這個值乡摹,DIskLruCache會清除一些緩存

 long DISK_CACHE_SIZE=1024*1024*50;
        File diskCacheDir=this.getCacheDir();
        if(!diskCacheDir.exists()){
            diskCacheDir.mkdir();
        }
mDiskLruCache=DIsLruCache.open(diskCacheDir,1,1,DISK_CACHE_SIZE);

DiskLruCache的緩存添加
通過Editor完成的,Editor表示一個緩存對象的編輯對象采转,首先需要獲取圖片url所對應(yīng)的key聪廉,然后通過key就可以通過edit()來獲取到Editor對象,如果這個緩存正在編輯則edit()會返回空故慈,即不允許同事彼岸奇偶及一個緩存對象板熊,一般采用url的md5值來表示key丢胚。
通過Editor可以獲取到一個文件輸出流再將其寫入到文件系統(tǒng)上狮崩。
通過editor.commit()來進(jìn)行提交递雀,如果發(fā)生異常則調(diào)用abort()來回退整個操作瓦戚。
DiskLruCache的緩存查找
查找過程也是需要將url轉(zhuǎn)化為key值通過DiskLruCache的get方法獲取到Snapshot對象蛔钙,通過它可以得到緩存圖片的文件輸出流 有了它就可以獲取到bitmap對象了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末竞阐,一起剝皮案震驚了整個濱河市祟辟,隨后出現(xiàn)的幾起案子必孤,更是在濱河造成了極大的恐慌闸度,老刑警劉巖竭贩,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異莺禁,居然都是意外死亡留量,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來楼熄,“玉大人忆绰,你說我怎么就攤上這事】善瘢” “怎么了错敢?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長青柄。 經(jīng)常有香客問我伐债,道長,這世上最難降的妖魔是什么致开? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任峰锁,我火速辦了婚禮,結(jié)果婚禮上双戳,老公的妹妹穿的比我還像新娘虹蒋。我一直安慰自己,他們只是感情好飒货,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布魄衅。 她就那樣靜靜地躺著,像睡著了一般塘辅。 火紅的嫁衣襯著肌膚如雪晃虫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天扣墩,我揣著相機(jī)與錄音哲银,去河邊找鬼。 笑死呻惕,一個胖子當(dāng)著我的面吹牛荆责,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亚脆,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼做院,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了濒持?” 一聲冷哼從身側(cè)響起键耕,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柑营,沒想到半個月后郁竟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡由境,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年棚亩,在試婚紗的時候發(fā)現(xiàn)自己被綠了蓖议。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡讥蟆,死狀恐怖勒虾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瘸彤,我是刑警寧澤修然,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站质况,受9級特大地震影響愕宋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜结榄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一中贝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧臼朗,春花似錦邻寿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挡毅,卻和暖如春蒜撮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背跪呈。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工淀弹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人庆械。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像菌赖,于是被迫代替她去往敵國和親缭乘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評論 2 361

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