/**
* 本文原創
* BUT
* 能夠隨意轉載到任何網站或者App
* BUT
* 轉載也要按「基本法」
* SO
* 請註明原文出處和做者
*/
官方源碼地址php
前言
雖然標題是fresco分析(一),可是並不表明會有2345的啦。
內容基本按流水式發展,大致和本身分析這個庫的流程一致,代碼好久前大概看了一天,可是沒有作任何記錄,此次算是權當記錄一番,復看了半天,可是,畫圖畫得想撞牆(逃。
然而,圖可能畫的並不很規範,看懂就行。
圖片加載庫很多,主流volley,universal imageloader, glide,picasso,fresco。
看上fresco的緣由:
介紹:
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):
其餘:
因爲整個庫的東西包含不少,功能性和擴展性很強,並且有不少巧妙的設計,本文沒法一一詳述,上面分析的都是庫的總體框架,雖然整個庫不小,可是其實架子就上面一點東西而已。
下面羅列出其餘一些須要關注的
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確實提供了很強大的功能,支持上也很完善。
可是,對比其餘相似庫仍是不一樣的,天然優缺點都存在。
(-)
- 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優缺點,因爲沒有在實際項目中使用,因此沒有詳細數據,
有待繼續確認,可是庫確實比較大,這是比較顯而易見的。
~~~文卒~~~