Android圖片加載

老生常談了,但是還是有很多細節(jié)不知道的。先挖個坑,后面慢慢埋~

圖片加載框架?

  1. Picasso
  2. Glide
  3. Fresco

Picasso:

Picasso :和Square的網(wǎng)絡庫一起能發(fā)揮最大作用,因為Picasso可以選擇將網(wǎng)絡請求的緩存部分交給了okhttp實現(xiàn)。

Glide:模仿了Picasso的API,而且在他的基礎上加了很多的擴展(比如gif等支持),Glide默認的Bitmap格式是RGB_565,比    Picasso默認的ARGB_8888格式的內(nèi)存開銷要小一半;Picasso緩存的是全尺寸的(只緩存一種),而Glide緩存的是跟ImageView尺寸相同的(即56*56和128*128是兩個緩存) 。

FB的圖片加載框架Fresco:最大的優(yōu)勢在于5.0以下(最低2.3)的bitmap加載。在5.0以下系統(tǒng),F(xiàn)resco將圖片放到一個特別的內(nèi)存區(qū)域(Ashmem區(qū))。當然,在圖片不顯示的時候,占用的內(nèi)存會自動被釋放。這會使得APP更加流暢,減少因圖片內(nèi)存占用而引發(fā)的OOM。為什么說是5.0以下,因為在5.0以后系統(tǒng)默認就是存儲在Ashmem區(qū)了。

Fresco性能上的優(yōu)點
優(yōu)一:
1、支持webp格式的圖片,是Google官方推行的,它的大小比其它格式圖片的大小要小一半左右,目前各個大公司都漸入的使用這種圖片格式了,比如:Youtube、Gmail、淘寶、QQ空間等都已嘗鮮,使用該格式最大的優(yōu)點就是輕量、省流量、圖片加載迅速。而Fresco是通過jni來實現(xiàn)支持WebP格式圖片。

優(yōu)二:
2、5.0以下系統(tǒng):使用”ashmem”(匿名共享內(nèi)存)區(qū)域存儲Bitmap緩存,這樣Bitmap對象的創(chuàng)建、釋放將永遠不會觸發(fā)GC,關于”ashmem”存儲區(qū)域,它是一個不在Java堆區(qū)的一片存儲內(nèi)存空間,它的管理由Linux內(nèi)核驅動管理,不必深究,只要知道這塊存儲區(qū)域是別于堆內(nèi)存之外的一塊空間就行了,且這塊空間是可以多進程共享的,GC的活動不會影響到它。5.0以上系統(tǒng),由于內(nèi)存管理的優(yōu)化,所以對于5.0以上的系統(tǒng)Fresco將Bitmap緩存直接放到了堆內(nèi)存中。

關于”ashmem”的存儲區(qū)域,我們的應用程序并不能像訪問堆內(nèi)存一樣直接訪問這塊內(nèi)存塊,但是也有一些例外,對于Bitmap而言,有一種為”Purgeable Bitmap”可擦除的Bitmap位圖是存儲在這塊內(nèi)存區(qū)域中的,BitmapFactory.Options中有這么一個屬性 inPurgeable :

BitmapFactory.Options = new BitmapFactory.Options();
options.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options);
所以通過配置inPurgeable = true這個屬性,這樣解碼出來的Bitmap位圖就存儲在”ashmem”區(qū)域中,之后用到”ashmem”中得圖片時,則把這個圖片從這個區(qū)域中取出來,渲染完畢后則放回這個位置。

既然Fresco中Bitmap緩存在5.0以前是放在”ashmem”中,GC并不會回收它們,且也不會被”ashmeme”內(nèi)置的清除機制回收它們,所以這樣雖然使得在堆中不會造成內(nèi)存泄露,而在這塊區(qū)域可能造成內(nèi)存泄露,F(xiàn)resco中采取的辦法則是使用引用計數(shù)的方式,其中有一個SharedReference這個類,這個類中有這么兩個方法:addReference()和deleteReference(),通過這兩個基本方法來對引用進行計數(shù),一旦計數(shù)為零時,則對應的資源將會清除(如:Bitmap.recycle()等),而Fresco為了考慮更容易被我們使用,又提供了一個CloseableReference類,該類可以說是SharedReference類上功能的封裝,CloseableReference同時也實現(xiàn)了Cloneable、Closeable接口,它在調用.clone()方法時同時會調用addReference()來增加一個引用計數(shù),在調用.close()方法時同時會調用deleteReference()來刪除一個引用計數(shù),所以在使用Fresco的使用,我們都是與CloseableReference類打交道,使用CloseableReference必須遵循以下兩條規(guī)則:

1、在賦值CloseableReference給新對象的時候,調用.clone()進行賦值

2、在超出作用域范圍的時候,必須調用.close(),通常會在finally代碼塊中調用

void gee() {
CloseableReference<Val> ref = foo();
try {
haa(ref);
} finally {
ref.close();
}
}
遵循這些規(guī)則可以有效地防止內(nèi)存泄漏。

優(yōu)三:
3、使用了三級緩存:Bitmap緩存+未解碼圖片緩存+硬盤緩存。其中前兩個就是內(nèi)存緩存,Bitmap緩存根據(jù)系統(tǒng)版本不同放在了不同內(nèi)存區(qū)域中,而未解碼圖片的緩存只在堆內(nèi)存中,F(xiàn)resco分了兩步做內(nèi)存緩存,這樣做有什么好處呢?第一個好處就如上的第二條,第二個好處是加快圖片的加載速度,F(xiàn)resco的加載圖片的流程為:查找Bitmap緩存中是否存在,存在則直接返回Bitmap直接使用,不存在則查找未解碼圖片的緩存,如果存在則進行Decode成Bitmap然后直接使用并加入Bitmap緩存中,如果未解碼圖片緩存中查找不到,則進行硬盤緩存的檢查,如有,則進行IO、轉化、解碼等一系列操作,最后成Bitmap供我們直接使用,并把未解碼(Encode)的圖片加入未解碼圖片緩存,把Bitmap加入Bitmap緩存中,如硬盤緩存中沒有,則進行Network操作下載圖片,然后加入到各個緩存中。

既然Fresco使用了三級緩存,而有兩級是內(nèi)存緩存,所以當我們的App在后臺時或者在內(nèi)存低的情況下在onLowMemory()方法中,我們應該手動清除應用的內(nèi)存緩存,我們可以使用下面的方式:

    ImagePipeline imagePipeline = Fresco.getImagePipeline();
    //清空內(nèi)存緩存(包括Bitmap緩存和未解碼圖片的緩存)
    imagePipeline.clearMemoryCaches();
    //清空硬盤緩存,一般在設置界面供用戶手動清理
    imagePipeline.clearDiskCaches();

    //同時清理內(nèi)存緩存和硬盤緩存
    imagePipeline.clearCaches();

3.總結:
Picasso所能實現(xiàn)的功能,Glide都能做,無非是所需的設置不同。但是Picasso體積比起Glide小太多如果項目中網(wǎng)絡請求本身用的就是okhttp或者retrofit(本質還是okhttp),那么建議用Picasso,體積會小很多(Square全家桶的干活)。Glide的好處是大型的圖片流,比如gif、Video,如果你們是做美拍、愛拍這種視頻類應用,建議使用。
Fresco在5.0以下的內(nèi)存優(yōu)化非常好,代價就是體積也非常的大,按體積算Fresco>Glide>Picasso
不過在使用起來也有些不便(小建議:他只能用內(nèi)置的一個ImageView來實現(xiàn)這些功能,用起來比較麻煩,我們通常是根據(jù)Fresco自己改改,直接使用他的Bitmap層)

MemoryFile 可以用來測試共享內(nèi)存

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,701評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,691評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,974評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,694評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,026評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,193評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,719評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,442評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,668評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,846評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,255評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,592評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,394評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

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