前言?
Fresco android圖片加載的框架,facebook出品。
本文是對Fresco框架源碼的閱讀學習后的記錄,主要是理清三個主要類的之間的關系。
本篇目錄
? ? ? Fresco框架的MVC模式
? ? ? Fresco的DraweeView、DraweeHierarchy、DraweeController的簡單介紹
? ? ? Fresco的DraweeView、DraweeHierarchy、DraweeController的創建順序
一、Fresco 框架的 MVC模式
? ? ? View ? ? ? ? ? ??DraweeView
? ? ? Model ? ? ? ? ??DraweeHierarchy
? ? ? Controleer ??DraweeController
其中DraweeHierarchy和DraweeController保存在DraweeHolder中,需要從DraweeHolder中get方式得到。
目的是將DraweeHierarchy和DraweeController封裝在一起,解耦出來。
如果要自定義DraweeView只需要在類中新添DraweeHolder類就可以比較方便地擁有DraweeHierarchy和DraweeController了。
二、DraweeView、DraweeHierarchy、DraweeController的簡單介紹
V-DraweeView
SimpleDraweeViewView
SimpleDraweeView為開發人員使用Fresco加載圖片的直接創建對象,控件對外的表層的model,只提供簡單setImageURL方法,最接近開發者,較為復雜的邏輯在頂層父類實現。
作用:修改顯示圖片URL
public void setImageURI(Uri uri)
public void setImageURI(@Nullable String uriString)
public void setImageURI(@Nullable String uriString, @Nullable Object callerContext)
public void setImageURI(Uri uri, @Nullable Object callerContext)
GenericDraweeView
其方法只有一個,在其構造方法中被調用。
作用:初始化DraweeHierarchy
protected void inflateHierarchy(Context context, @Nullable AttributeSet attrs)
DraweeView
0.11.0版本依然是繼承自ImageView,看網上說后面會直接繼承自View,負責圖片的顯示,其中重要的一個方法:getTopLevelDrawable() 用來獲得Hierarchy儲存的頂層圖片進行顯示。
作用:具體的圖片內容
@Nullable public Drawable getTopLevelDrawable() {
? ? ? return mDraweeHolder.getTopLevelDrawable();
}
DraweeHolder:
public Drawable getTopLevelDrawable() {
? ? ? return mHierarchy == null ? null : mHierarchy.getTopLevelDrawable();
}
M-DraweeHierarchy
SettableDraweeHierarchy、DraweeHierarchy皆為接口類,GenericDraweeHierarchy實現他們的方法。
DraweeHierarchy
接口類,只有一個簡單卻重要的方法,FaceDrawable是個圖片數組,里面包含所需要的所有圖片。
作用:獲得在Hierarchy中的FadeDrawable中儲存的頂層圖片進行顯示
Drawable getTopLevelDrawable();
SettableDraweeHierarchy
里面的接口方法均為提供給Controller調用來控制圖像,在GenericDraweeHierarchy中實現
作用:定義對外提供的控制圖片相關操作的方法
void reset();
void setImage(Drawable drawable, float progress, boolean immediate);
void setProgress(float progress, boolean immediate);
void setFailure(Throwable throwable); void setRetry(Throwable throwable);
void setControllerOverlay(Drawable drawable);
GenericDraweeHierarchy
GenericDraweeHierarchy實現了父類的接口,提供給Controller調用來控制圖片的顯示。
其中要三個主要的Drawable對象:
FadeDrawable,它存儲了需要到的圖片資源,包括顯示圖片、加載圖片、失敗時顯示的圖片等等。繼承自ArrayDrawable,層級類圖片集合。會選擇圖片數組中的最后一張進行顯示。
RootDrawable(mTopLevelDrawable)即儲存了FadeDrawable的頂層圖片,為要即將要顯示的圖片
ForwardingDrawable(mActualImageWrapper) 即儲存了目標圖片
其中FadeDrawable類中的主要方法有:
public void setTransitionDuration(int durationMs);\\設置隱藏/顯示圖層漸變動畫時間(默認為300ms)
public void fadeInLayer(int index);\\顯示指定圖層
public void fadeOutLayer(int index);\\隱藏指定圖層
public void fadeInAllLayers();\\顯示所有圖層
public void fadeOutAllLayers();\\隱藏所有圖層
public void fadeToLayer(int index);\\顯示指定圖層同時隱藏其他圖層
public void fadeUpToLayer(int index);\\隱藏數組下標<=index的圖層
以上方法 會修改boolean[] mIsLayerOn布爾數組,來判斷是否顯示圖片。
C-DraweeController
在初始化框架時,會創建一個PipelineDraweeControllerBuilderSupplier,并保存在SimpleDraweeView和Fresco兩個類中,以靜態變量的方式,所以DraweeController的創建有兩個入口。
一、使用Fresco類方式(代碼中創建):
DraweeController的創建過程:
1.調用Fresco.newDraweeControllerBuilder(),獲得PipelineDraweeControllerBuilder。
2.再調用PipelineDraweeControllerBuilder的父類AbstractDraweeControllerBuilder 的 build()方法,build()又調用了obtainController(),該方法又調用了PipelineDraweeControllerBuilder的obtainController(),獲得PipelineDraweeController。
3.最后build()方法返回的是,獲得的PipelineDraweeController的父類AbstractDraweeController。
這里有點繞,大致的順序是:
Fresco.newDraweeControllerBuilder()獲得PipelineDraweeControllerBuilder
class Fresco
--public static PipelineDraweeControllerBuilder newDraweeControllerBuilder()?
class PipelineDraweeControllerBuilderSupplier
--public PipelineDraweeControllerBuilder get()
PipelineDraweeControllerBuilder.build()獲得AbstractDraweeController
class AbstractDraweeControllerBuilder
--public AbstractDraweeController build()
---protected AbstractDraweeController buildController()
----protected abstract AbstractDraweeController obtainController()
class PipelineDraweeControllerBuilder
--protected PipelineDraweeController obtainController()
二、使用默認方式(不用自己創建):
提供給SimpleDraweeView創建Controller的方法只有簡單的幾個,即在SimpleDraweeControllerBuilder中的接口方法。
SimpleDraweeControllerBuilder
SimpleDraweeControllerBuilder setCallerContext(Object callerContext);
SimpleDraweeControllerBuilder setUri(Uri uri);
SimpleDraweeControllerBuilder setUri(@Nullable String uriString);
SimpleDraweeControllerBuilder setOldController(@Nullable DraweeController oldController);
DraweeController build();
總結:如果沒有特別需求,則不用自己創建Controller去操作View(第二種),如果需要加上一些圖片加載監聽之類的操作,則自己創建Controller去操作(第一種)。
三、Fresco的DraweeView、DraweeHierarchy、DraweeController的創建順序
初始化順序為:
1.DraweeView
其余都為DraweeView對象中的類,所以先有DraweeView
2.DraweeHolder (在DraweeView的init()方法中創建 保存在DraweeView中)
DraweeView:
DraweeHolder.create(null, context)
DraweeHolder:
public static?<DH extends DraweeHierarchy>DraweeHolder<DH>?create(
? ? @Nullable DH hierarchy,
? ? Context context) {
DraweeHolder holder =newDraweeHolder(hierarchy);
holder.registerWithContext(context);returnholder;
}
3.DraweeHierarchy (在GenericDraweeView的inflateHierarchy()方法中創建 保存在DraweeHolder和DraweeController中)
GenericDraweeView:
protected void inflateHierarchy(Context context, @Nullable AttributeSet attrs) {
GenericDraweeHierarchyBuilder builder = ? ? GenericDraweeHierarchyInflater.inflateBuilder(context, attrs);
setAspectRatio(builder.getDesiredAspectRatio());
setHierarchy(builder.build());
}
4.DraweeController
并不預先創建,而是在使用到控件的時候動態創建,有兩種創建途徑,但兩種都是通過拿到DraweeControllerBuilderSupplier 用建造器模式去創建Controller,上面已經講過。
①.調用SimpleDraweeView中的setImageURL(),源碼中已寫好創建Controller的代碼,只設置圖片URL
②.在代碼中使用到的時候動態創建,能自定義更多關于圖片的屬性方法,如需要監聽一張GIF圖片的播放結束事件,就需要自己在代碼中動態創建(高版本已經把對gif的支持單獨出去)