本教程內(nèi)容來源于:http://fresco-cn.org
采用 知識共享 署名 4.0 國際 許可協(xié)議 進(jìn)行許可
總有一些時候,DraweeViews
是滿足不了需求的,在展示圖片的時候,我們還需要展示一些其他的內(nèi)容,或者支持一些其他的操作。在同一個View里,我們可能會想顯示一張或者多張圖。
在自定義View中,F(xiàn)resco 提供了兩個類來負(fù)責(zé)圖片的展現(xiàn):
DraweeHolder
單圖情況下用。MultiDraweeHolder
多圖情況下用。Android 呈現(xiàn)View對象,只有View對象才能得到一些系統(tǒng)事件的通知。DraweeViews
處理這些事件通知,高效地管理內(nèi)存。使用DraweeHolder
時,你需要自己實(shí)現(xiàn)這幾個方法。
如果沒按照以下步驟實(shí)現(xiàn)的話,很可能會引起內(nèi)存泄露
當(dāng)圖片不再在View上顯示時,比如滑動時View滑動到屏幕外,或者不再繪制,圖片就不應(yīng)該再存在在內(nèi)存中。Drawees 監(jiān)聽這些事情,并負(fù)責(zé)釋放內(nèi)存。當(dāng)圖片又需要顯示時,重新加載。
這些在DraweeView
中是自動的,但是在自定義View中,需要我們自己去操作,如下:
DraweeHolder mDraweeHolder;
@Override
public void onDetachedFromWindow() {
super.onDetachedToWindow();
mDraweeHolder.onDetach();
}
@Override
public void onStartTemporaryDetach() {
super.onStartTemporaryDetach();
mDraweeHolder.onDetach();
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
mDraweeHolder.onAttach();
}
@Override
public void onFinishTemporaryDetach() {
super.onFinishTemporaryDetach();
mDraweeHolder.onAttach();
}
如果你啟用了點(diǎn)擊重新加載,在自定義View中,需要這樣:
@Override
public boolean onTouchEvent(MotionEvent event) {
return mDraweeHolder.onTouchEvent(event) || super.onTouchEvent(event);
}
Drawable drawable = mDraweeHolder.getHierarchy().getTopLevelDrawable();
drawable.setBounds(...);
否則圖片將不會出現(xiàn)
verifyDrawable:
@Override
protected boolean verifyDrawable(Drawable who) {
if (who == mDraweeHolder.getHierarchy().getTopLevelDrawable()) {
return true;
}
// 對其他Drawable的驗(yàn)證邏輯
}
invalidateDrawable
處理了圖片占用的那塊區(qū)域。這同樣需要非常小心和細(xì)致
我們推薦如下實(shí)現(xiàn)構(gòu)造函數(shù):
init
方法。init
方法中執(zhí)行初始化操作。即,不要在構(gòu)造函數(shù)中用this
來調(diào)用另外一個構(gòu)造。
這樣可以保證,不管調(diào)用哪個構(gòu)造,都可以正確地執(zhí)行初始化流程。然后在init
方法中創(chuàng)建holder。
如果有可能,只在View創(chuàng)建時,創(chuàng)建Drawees。創(chuàng)建DraweeHierarchy開銷較大,最好只做一次。
class CustomView extends View {
DraweeHolder<GenericDraweeHierarchy> mDraweeHolder;
// constructors following above pattern
private void init() {
GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(getResources());
.set...
.set...
.build();
mDraweeHolder = DraweeHolder.create(hierarchy, context);
}
}
使用controller builder創(chuàng)建DraweeController,然后調(diào)用holder的setController
方法,而不是設(shè)置給自定義View。
DraweeController controller = Fresco.newControllerBuilder()
.setUri(uri)
.setOldController(mDraweeHolder.getController())
.build();
mDraweeHolder.setController(controller);
和DraweeHolder
相比,MultiDraweeHolder
有 add
, remove
, clear
等方法可以操作Drawees。如下:
MultiDraweeHolder<GenericDraweeHierarchy> mMultiDraweeHolder;
private void init() {
GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(getResources());
.set...
.build();
mMultiDraweeHolder = new MultiDraweeHolder<GenericDraweeHierarchy>();
mMultiDraweeHolder.add(new DraweeHolder<GenericDraweeHierarchy>(hierarchy, context));
// repeat for more hierarchies
}
同樣,也需要處理系統(tǒng)事件,設(shè)置聲音等等,就想處理單個DraweeHolder
那樣。