/**
* 本文原創
* BUT
* 可以隨意轉載到任何網站或者App
* BUT
* 轉載也要按“基本法”
* SO
* 請注明原文出處和作者
*/
fresco官方高大上介紹(1)(注意:前方有堵牆)
fresco官方高大上介紹(2)(注意:前方有堵牆)
前言
雖然標題是fresco分析(一),但是並不代表會有2345的啦。
內容基本按流水式發展,大體和自己分析這個庫的流程一致,代碼很久前大概看了一天,但是沒有做任何記錄,這次算是權當記錄一番,復看了半天,但是,畫圖畫得想撞牆(逃。
然而,圖可能畫的並不很規范,看懂就行。
圖片加載庫不少,主流volley,universal imageloader, glide,picasso,fresco。
看上fresco的原因:
- facebook出品
- 代碼多啊
介紹:
fresco,facebook開源的針對android應用的圖片加載框架,高效和功能齊全。
- 支持加載網絡,本地存儲和資源圖片;
- 提供三級緩存(二級memory和一級internal storage);
- 支持JPEGs,PNGs,GIFs,WEBPs等,還支持Progressive JPEG,優秀的動畫支持;
- 圖片圓角,scale,自定義背景,overlays等等;
- 優秀的內存管理;
- 2.3(Gingerbread)或以上。
(其實上面都是多余的啦~~~)
正文開始
本文涉及得圖片可能都不是太規范,如果有強迫症,請忽略
內容沒有大量代碼,怕長篇累牘,所以只能是個大概,慎讀。
工程
clone代碼下來,工程的樣子大概就是這樣的了:

簡略說一下project structure:
- sample module下面是例子,里面有好幾個例子工程,例如demo等;
- drawee module,主要是ui相關的東西,例如DraweeView, drawable相關的類等;
- imagepipeline module,整個工程的核心,圖片加載,內存、緩存管理,bitmap處理等等核心邏輯;
- fbcore module,可以說是基礎類庫,一些工具類,基礎接口,文件處理等等;
- drawee backends,就是基於drawee module里面的某些接口的具體實現,例如如果曾經使用volley的,可以繼續使用volley作為圖片加載的框架一部分去做加載圖片;
- imagepipeline backends,也是基於imagepipeline module中某些接口的具體實現,例如http請求是使用okhttp的,可以繼續使用okhttp實現;
project structure大概就是這樣,紅色標出的是最需要關注的三個module,其他都是easy job。
用法:
直接上代碼:
xml中:
<com.facebook.drawee.view.SimpleDraweeView android:id="@+id/baseline_jpeg" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" fresco:actualImageScaleType="fitCenter" />
代碼:
1 Uri uri = Uri.parse("http://省略");// 2 ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) 3 .setProgressiveRenderingEnabled(true) 4 .build(); 5 DraweeController controller = Fresco.newDraweeControllerBuilder() 6 .setImageRequest(request) 7 .build(); 8 mProgressiveJpegView.setController(controller);
代碼比較簡單,比較容易懂,但是相對其他的圖片加載框架而言,感覺這樣的調用還是相對復雜。當然自己可以繼續封裝,減少不必要的大量重復的代碼。
流程分析:
分析流程基本是自己分析開源項目主要做的第一件事情,一遍流程下來,大概就能摸索清楚了。
然后,就有了下面這張圖,圖大,
手機黨慎點~~~
想看細節點,可點擊看大圖或者下載。。。。

(流程選的是demo例子里面網絡加載圖片的流程,其他的大概差不多。)

(
流程圖里面省略掉很多細節,但是主要的流程都描述出來了)(圖畫的我啊。。。。)
一個完整的請求,到響應流程就是這樣,相當的復雜,有耐心可以仔細的看看(這渣圖也很難有耐心的了)。
雖然復雜,但是確實從實現上看,擴展性和功能性來看,還是相當完善的,正如facebook自己所講:
Several excellent open source libraries exist that perform these sequences — Picasso, Universal Image Loader, Glide, and Volley, to name a few. All of these have made important contributions to Android development. We believe our new library goes further in several important ways.
關鍵點:
關鍵點的分析,主要是着眼於一些關鍵的接口和類。這里分module來進行。
先分析
drawee module的,主要下面三個:
- DraweeView
- DraweeHierarchy
- DraweeController
這三個類的關系大概就是一個MVC的模式:
- DraweeView繼承ImageView,即V,負責展現DraweeHierarchy;
- DraweeHierarchy是M,可以認為它由多層的drawable組成,每一層為圖片提供某種特定的功能,例如scale,fade-in,layering等等;
- DraweeController是C,處理核心的控制邏輯。例如向pipeline(或者其他圖片加載庫)發出請求,並接收相應事件,並根據不同事件控制DraweeHierarchy;還有,從DraweeView接收事件,然后做出取消網絡請求、回收資源等操作。
具體細節這里不展開討論,但是得提一個就是,DraweeView設置圖片使用的並不是setBitmap方法,所有的操作都是對DraweeView的drawable進行操作,不管是更新,圓角等等。
然后分析
fbcore:
- DataSource
- DataSubscriber
fbcore里面基本都是一些基礎類,這兩個接口也不例外。
- DataSource,Java里面的Futures的替代品,從字面意思就知道,它代表數據來源,它和Futures不同的是,可以有一系列的result,而不是一個。
- DataSubscriber,和DataSource對應,用於接收從DataSource返回的結果,從字面意思也能知道大概作用
DataSource的任何狀態改變,DataSubscriber理應接收相應的事件,然后處理。
簡單理解就是,DataSource代表數據處理流程和結果,DataSubscriber就像Callback一樣,不斷接收事件。
這兩個都是接口,有很多的不同實現,這里不討論。主要的兩個實現類是AbstractDataSource和BaseDataSubcriber,其他的實現基本都是繼承這兩個抽象類的。
最后是
imagepipeline,最核心的模塊。
雖然是核心模塊,但是核心模塊其實也就幾個關鍵點,面向接口編程指導下,基本上找到關鍵的接口,整個框架就清晰了。
- ImagePipeline和ImagePipelineConfig
- Producer和Consumer
- ImagePipeline是整個module的entry point,獲取圖片的主要接口都是通過它來調用 。
- ImagePipelineConfig顧名思義,是用來配置ImagePipeline的屬性的,例如內存緩存配置,本地文件緩存配置,bitmapconfig等等。
Producer和
Cosumer明顯的
生產者和
消費者模式了。
Producer在imagepipeline在有各種各樣的實現,超過10種以上。例如包含
NetworkFetcherProducer,
LocalAssetFetcherProducer,
LocalFileFetchProducer等等。
而這些producer就是最終”產出“圖片的地方,上層圖片的來源(
DataSource<T>)就是從此處得到的。當然producer也包含一些具體的處理,例如對圖片進行encode,resize等等。不同的處理可能對應不同的producer。
而眾多producer都可以通過
ProducerFactory這個工廠類獲得。而設計上有個巧妙的地方就是,producer往往是一層嵌一層的,什么意思,基本就是類似於我們平常用的io stream一樣:
new BufferedReader(new InputStreamReader(new FileInputStream(file)));
就是通過這種方式,底層上來的原始數據,一層層的進行特定的處理,然后產出一個最后的結果,便於上層直接進行使用。例如:
public <T> ThreadHandoffProducer<T> newBackgroundThreadHandoffProducer( Producer<T> inputProducer) { return new ThreadHandoffProducer<T>( mExecutorSupplier.forLightweightBackgroundTasks(), inputProducer); }
參數也是一個producer,然后可以不斷的嵌套。這個在impineline里面叫做producer sequence(producer鏈?)。對應的有
ProducerSequenceFactory這個工廠類,用它來獲得不同的producer sequence。
Consumer就是用來接收producer的產出結果的,最后一步步回調回到上層ui。
運作:
整個庫運行的流程(其實是一個activity diagram)簡略如下(詳細的可以
加倍耐心參看上面的sequence diagram):

框架:
框架大概是這樣(個人總結):


ImagePipeline框架圖
其他:
由於整個庫的東西包含很多,功能性和擴展性很強,而且有很多巧妙的設計,本文無法一一詳述,上面分析的都是庫的整體框架,雖然整個庫不小,但是其實架子就上面一點東西而已。
下面羅列出其他一些需要關注的
key point:
- 緩存機制(三級緩存);內存緩存是如何管理的,文件緩存是怎么存儲和讀取的;
- 內存管理,防止OOM,主要是bitmap等內存占用大的對象處理;主要用到的是SharedReference這個類,相關的還有CloseableReference,整個庫隨處可見,其實就是一個支持引用計數的對象,類型於C++的shared_ptr,當計數為0時,就可以釋放。
- 不同的圖片格式對應的處理方式,圖片處理涉及到一些第三方的native庫,例如giflib,libjpeg,libpng等;
- 各種不同的drawable的實現,特別是progressive drawable和gif這些復雜的實現,和DraweeHierarchy對圖片切換的實現;
- 多線程處理。為什么叫pipeline呢?這也是值得深究的。pipeline對於熟悉操作系統的都知道,現代cpu的架構都是pipelined的,以實現parallelism。個人覺得,imagepipeline也是有這個意思,把一個任務拆分成多個獨立單元,然后並行處理。官方文檔中也有所提及。有如圖:
- 整個庫實現設計上,各種設計模式亂入。builder,factory,wrapper,producer/consumer,adapter等等。
- 其他細節,自己發掘。。。。
總結:
fresco確實提供了很強大的功能,支持上也很完善。
但是,對比其他類似庫還是不同的,自然優缺點都存在。
優缺點參考的是:
http://stackoverflow.com/questions/29363321/picasso-v-s-imageloader-v-s-fresco-vs-glide,這里面對幾個圖片加載庫進行了對比,fresco
優缺點如下:
(-)
- Huge size of library
- App freeze while loading big images from internet into ListView
- Huge size of cache
(+)
- Pretty fast image loader
- A lot of functionality
- Huge size of library
- App freeze while loading big images from internet into ListView
- Huge size of cache
(+)
- Pretty fast image loader
- A lot of functionality
fresco優缺點,由於沒有在實際項目中使用,所以沒有詳細數據,
有待繼續確認,但是庫確實比較大,這是比較顯而易見的。
~~~文卒~~~