Android最好用瓷蛙、最強大的圖片加載框架:Fresco的簡單實用教程
貌似有2個月沒寫博客了悼瓮,原因還跟以往一樣,忙+懶艰猬,其實二者是相輔相成的横堡,忙的時候要想抽點時間也還是有的,但一忙就懶得管工作以外的事情了冠桃,一 來二去也就會拖延很久命贴。最近把公司項目中的圖片加載框架由Universal-Image-Loader換成了Fresco,感覺有必要做個記錄食听。
一個內容充實的應用胸蛛,圖片是必不可少的。而圖片往往體積比較大碳蛋,從服務器下載圖片那肯定是要用異步線程來做的胚泌,在UI主線程中盡量不做任何耗時操作 是每個Android開發(fā)者應該遵循的準則。你可以自己來寫如何加載圖片肃弟,但多數(shù)開發(fā)者的能力可能不足以完成一個足夠好的圖片加載框架玷室,好在網(wǎng)上資源豐 富,已經有好幾個開源的圖片加載框架供我們選擇笤受,它們都能比較好的滿足我們的需求穷缤,可以讓開發(fā)者不用太專注于圖片的處理。比較有名的有 Universal-Image-Loader箩兽、Picasso津肛、Volley,以及今天的主角——Fresco汗贫。
要說身坐,我們項目中原來Universal-Image-Loader用的也好好的,沒什么問題落包,但有更好的技術還是要及時跟進的部蛇。Fresco是 Facebook發(fā)布的一款開源框架,號稱是目前最強的Android圖片加載庫咐蝇,在內存方面的表現(xiàn)極為優(yōu)秀涯鲁,既然有如此信心,那么至少我應該先嘗試一 下有序,若真的好用抹腿,就替換掉UIL了。
對于Fresco的一些介紹旭寿,就不多說了警绩,如果你感興趣肯定會到網(wǎng)上找一些相關的資料,建議你到官網(wǎng)查 看:http://frescolib.org/盅称。當然了房蝉,國內的大神也對這個網(wǎng)站進行了翻譯僚匆,如果你英語水平比較捉急微渠,請到http: //fresco-cn.org/來進行觀摩搭幻,不過還是建議到官網(wǎng),因為你不知道什么時候會有更新逞盆,第三方的文檔會不及時檀蹋。
下面直接來一段代碼吧,看過就知道Fresco用起來是多么簡單了:
記住云芦,要想在項目中引入Fresco俯逾,只需要在Module的build.gradle文件的dependencies中添加一句話
1 compile 'com.facebook.fresco:fresco:0.7.0+'
至于Eclipse的用戶,呃舅逸,請自己到官網(wǎng)進行觀摩桌肴,有教程,但你真的還要對Android Studio視而不見繼續(xù)用Eclipse么……
主Activity代碼:
package com.kaelli.frescodemo;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.view.SimpleDraweeView;
public class MainActivity extends Activity {
private SimpleDraweeView mSimpleDraweeView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fresco.initialize(this);
setContentView(R.layout.activity_main);
mSimpleDraweeView = (SimpleDraweeView)findViewById(R.id.simpleDraweeView);
mSimpleDraweeView.setImageURI(Uri.parse("http://f2.topit.me/2/79/0a/1175191760a730a792o.jpg"));
}
}
相對應的布局文件:
XHTML
<?xml version="1.0" encoding="utf-8"?>
<com.facebook.drawee.view.SimpleDraweeView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:id="@+id/simpleDraweeView"
android:layout_width="match_parent"
android:layout_height="match_parent"
fresco:fadeDuration="300"
fresco:actualImageScaleType="fitCenter"
fresco:placeholderImage="@drawable/image1"
fresco:placeholderImageScaleType="fitCenter"
fresco:failureImage="@drawable/image1"
fresco:failureImageScaleType="fitCenter" />
程序的運行截圖如下:
FrescoDemo運行圖
看得出來琉历,F(xiàn)resco的一個很大的特點在于坠七,它自定義了一個SimpleDraweeView,而不是直接在ImageView上進行操作旗笔。你可 能會覺得這樣有些麻煩彪置,畢竟人家UIL是直接用普通的ImageView的,但Facebook這么做是有其道理的蝇恶。如果你有興趣拳魁,查看一下源碼,看得出 來目前SimpleDraweeView是繼承自ImageView的撮弧,然而很多ImageView的方法已經被@Deprecated掉了潘懊,不建議使用,而且其開發(fā)人員也表示今后的版本中贿衍,F(xiàn)resco的SimpleDraweeView將會直接繼承自View授舟,與ImageView再無關系。
使用Fresco有一些需要注意的地方:
1舌厨、一定不要忘了Fresco庫的初始化:
Fresco.initialize(this);
通常這一句將在Application的onCreate中是比較合適的岂却,如果只有一個Activity,那么加在Activity里也可以裙椭,但要在setContentView之前躏哩,也就是要先初始化庫,才能完成布局文件的加載揉燃。
?SimpleDraweeView的width和height屬性必須是明確值扫尺,而不能直接用wrap_content這種內容填充的數(shù)值,當然 有一種情況例外炊汤,就是寬度和高度有一個是固定的正驻,然后設置了二者的比例弊攘,則另一個可以用wrap_content,其實相當于二者都是固定的姑曙。
mSimpleDraweeView.setAspectRatio(1.33f); // 設置寬高比為4:3
3襟交、正常情況下,一個SimpleDraweeView的各種屬性伤靠,既可以在布局文件里面設置(如上面的代碼)捣域,也可以在Java代碼里設置,作用 是一樣的宴合。但既然提到了“正常情況”焕梅,那就必然有非正常情況了:當SimpleDraweeView被被一些第三方自定義View包裹的時候,比如最常見 的卦洽,一個可下拉刷新的第三方ListView贞言,則此時在布局文件中的一些屬性居然是無效的!好吧阀蒂,根本原因我并沒有找到该窗,只能在代碼里面設置屬性了,仍然 沒有任何難度:
GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
GenericDraweeHierarchy hierarchy = builder
.setActualImageScaleType(ScalingUtils.ScaleType.FIT_CENTER)
.setPlaceholderImage(getResources().getDrawable(R.drawable.image1), ScalingUtils.ScaleType.FIT_CENTER)
.setFailureImage(getResources().getDrawable(R.drawable.image1), ScalingUtils.ScaleType.FIT_CENTER)
.build();
mSimpleDraweeView.setHierarchy(hierarchy);
一般來說脂新,安全起見挪捕,還是直接在Java代碼里寫比較好,布局文件里面只是聲明一個SimpleDraweeView就足夠了争便。
4级零、不要使用那些被@Deprecated的方法,盡管這些方法(如setImageResource或者setImageBitmap)是可用 的滞乙,但在以后的版本中也許就作廢了奏纪。Fresco的建議是,直接用setImageURI的方法來設置圖片斩启,即使是本地的圖片也用這種方法序调。
今天只寫了Fresco的最基本的用法,實際上可能很多人比較關心它的性能到底有多么出色兔簇,那么以后我會用它來跟Universal-Image-Loader還有Picasso進行對比缀台,這樣你就能知道碘勉,為什么要選擇Fresco了。
Android圖片加載庫對比:Universal-Image-Loader vs Glide vs Fresco vs Picasso幾大框架的選擇
翻了翻最近的一篇博客,居然是去年10月份的怔揩,也就是說半年多沒有寫點什么了丈探,顯然人一旦懶起來阴幌,連自己都會吃驚烟号。最近個人生活有很大的變化,當然并不是差的變化翻擒,那么工作上氓涣、學習上也要變好一點牛哺,最簡單的,自然是要變得勤快一點劳吠,別懶下去了引润。
對于很多Android App來說,都會有圖片加載的需求赴背,畢竟有圖片的App才能顯得更加多姿多彩椰拒。要實現(xiàn)圖片加載,其基礎的原理并不麻煩凰荚,大概有這么幾點:
?圖片應該是異步加載的,從網(wǎng)絡上下載圖片會是一個比較耗時的過程褒脯,如果是在UI主線程里進行便瑟,那么ANR肯定無法避免了。任何耗時操作都在異步線程里進行番川,這是一個Android開發(fā)者應有的基本素質到涂。
?圖片從網(wǎng)上下載完之后,需要在本地進行Bitmap的處理颁督,最重要的就是圖片的壓縮践啄。這一步是比較難辦的,壓縮的力度太大沉御,圖片的顯示效果就會比較差屿讽;壓縮的不夠,那么圖片就會占用大量內存吠裆,動輒就搞出OOM這種事情來伐谈。
?最好實現(xiàn)一個自己的緩存策略,即把圖片下載到本地memory和disk(其實就是Flash)中试疙,需要保存下來并有一定的策略诵棵,這樣下次再加載同樣的圖片的時候,就可以直接在本地加載而不需要去網(wǎng)絡下載了祝旷,大大提升了加載速度并節(jié)省了流量履澳,當然這一步也是比較麻煩的。
實現(xiàn)了以上3點怀跛,你就可以做出一個基本的圖片加載庫了距贷,當然,可能會比較粗糙敌完。實際上呢储耐,網(wǎng)上有大量的圖片加載庫,而且是開源的滨溉,最重要的在于什湘,這 些庫都有各自的緩存策略长赞,而且經過了大量開發(fā)者的實踐考驗,都很可靠闽撤。其中得哆,比較有名的有:Universal-Image-Loader、 Picasso哟旗、Volley贩据、Glide和Fresco,那么到底該如何選擇呢闸餐?
Universal-Image-Loader
這是一個很早就出現(xiàn)的圖片加載框架了饱亮,作者是大名鼎鼎的nostra13,UIL使用方便舍沙,而且自有多種緩存策略近上,如最大尺寸先刪除、時間最久刪除 等拂铡,使用它壹无,基本上不需要考慮太多的問題,可以把精力節(jié)省下來投入到開發(fā)的其他地方感帅。另外斗锭,UIL還支持圖片下載進度的監(jiān)聽,如果你有特殊需求失球,則可以在 圖片開始下載前岖是、剛開始下載等各個時間段來做一些額外的事情,非常方便她倘。而且UIL可以在View滾動的過程中暫停圖片的加載璧微,有利于提升界面的流暢度。 然而硬梁,作者前陣子(2015/11/27)宣布不再維護這個項目了前硫,換言之,以后它不會更新了——雖然有可能被其他開發(fā)者接手荧止,但考慮到現(xiàn)在圖片加載庫十 分豐富屹电,有這個興致的人怕是不多。如果你要開發(fā)新項目跃巡,可以不考慮UIL了危号,但如果是一個比較老而又龐大的項目并且使用了UIL,那么倒也不必太著急替換 它素邪,至少目前它還是能很好的完成圖片加載任務的外莲。
Picasso
來自于開源界名氣很大的Square公司(對,就是那個著名的JakeWharton大神所在的公司),總體來看它比較小巧偷线,但也有著一些自己的特 色磨确。比如,很特別的擁有統(tǒng)計功能声邦,可以知道使用了多少內存乏奥、緩存命中如何,另外它本身沒有什么緩存策略亥曹,而是依賴所用的網(wǎng)絡庫的緩存策略——嗯邓了,其實就是 依賴了OkHttp了。Picasso使用起來也是比較簡單的媳瞪,不過對于新項目來說骗炉,也不是很推薦,原因就在于材失,Glide比它更優(yōu)秀痕鳍,而且使用起來幾乎 是一樣的……
Glide
來自于bumptech,被Google官方所推薦龙巨,甚至在許多Android的原生應用中都采用了Glide來加載圖片,可見其受推崇的程度熊响。如果你知道Picasso和Glide的基本使用方法旨别,就會神奇的發(fā)現(xiàn),二者是很相似的:
Java
1
2
3 Picasso.with(context)
.load("image src url")
.into(ImageView);
1
2
3 Glide.with(context)
.load("image src url")
.into(ImageView);
從某種程度上說汗茄,Glide可以看作是Picasso的改進版秸弛。那么它又有什么獨特的優(yōu)勢呢?Glide不僅支持常見的jpg和png格式洪碳,還能顯 示gif動畫递览,甚至是視頻,換言之它已經不僅僅是一個普通的圖片加載庫了瞳腌,而是一個多媒體庫绞铃。另外一個優(yōu)勢是,Glide在內存方面的表現(xiàn)相當出色嫂侍,首先 它的圖片默認格式是RGB565儿捧,要比ARGB8888節(jié)省更多內存,而且它緩存的不是原始圖片挑宠,而是緩存了圖片的實際大小——比如加載的圖片是 19201080的大小菲盾,而在你的App中,顯示該圖片的ImageView大小只有1280720各淀,那么Glide就會很聰明的自動緩存 1280*720大小的圖片懒鉴。
Fresco
這個可以稱為是Android平臺上目前最為強大的圖片加載庫了,來源于地球人都知道的Facebook公司碎浇。與Glide一樣临谱,F(xiàn)resco也是 支持gif動畫顯示璃俗,而且在內存方面的表現(xiàn)更是無敵。由于將圖片放在Ashmem(匿名共享內存)中吴裤,大大降低了App的內存占用(因為Ashmem沒有 被統(tǒng)計到App的內存使用里)旧找,再加上各種神優(yōu)化,使得Fresco基本上告別了OOM麦牺,而且Fresco的圖片直接顯示為ARGB8888這種最高質量 的級別钮蛛,即使是在這種高質量的情況下依然保證了比其他庫更少的內存占用,不得不佩服Facebook的實力剖膳。而且類似于進度監(jiān)聽魏颓、緩存策略等,也是應有盡 有吱晒,總之作為一個圖片加載庫甸饱,F(xiàn)resco在功能和性能方面已經趨于完美了。
其他的之Volley
Google官方出品仑濒,質量其實也只能算是馬馬虎虎了叹话,事實上我更愿意把它當成是一款網(wǎng)絡庫——然而在這個領域它仍然被其他對手碾壓,so……就不多說了墩瞳。
該如何選擇圖片加載庫驼壶?
如果你手中的項目比較老舊,而且代碼量較大喉酌,你又沒什么時間去大改热凹,那么繼續(xù)維持當前的選擇是比較穩(wěn)妥的辦法。如果是新上馬的項目泪电,那么UIL由于 不再維護般妙、Picasso基本被Glide全方位超越,我推薦使用Glide或Fresco相速。如果你的App里碟渺,圖片特別多,而且都是很大和蚪、質量很高的圖 片止状,而且你不太在乎App的體積(這可能嗎?)攒霹,那么Fresco就是很好的選擇了怯疤,而Glide相比較Fresco要輕量一些,而且是Google官方 推薦催束,所以在多數(shù)時候集峦,會是開發(fā)者的首選。話說回來,如果你非常在意App的體積塔淤,不肯讓App多增加多余的1KB摘昌,那么,也許自己實現(xiàn)一個圖片加載庫也 是不錯的選擇哦高蜂,而且能很好的鍛煉自己的能力聪黎,何樂而不為呢?