從custom Drawable看invalidateSelf()

一鱼响、invalidateSelf()

參考(https://www.zybuluo.com/linux1s1s/note/93075)
我自己也嘗試著看源碼。不過(guò)不同的是在Drawable里面自己調(diào)用invalidateSelf(),而不是在view里面開(kāi)始筐骇。
1.一個(gè)繼承ImageView的自定義View铛纬,重寫(xiě)了setImageDrawble(Drawable drawable)唬滑。

@Override
public void setImageDrawable(Drawable drawable) {
    Tool.LI("WeatherAnimView setImageDrawable");
    Drawable d = getDrawable();
    if (d != null && d.equals(drawable)) { 
       return;
    }
    if (d != null && d instanceof WeatherDrawable) {
        ((WeatherDrawable) d).stopAnimation();
    } 
   super.setImageDrawable(drawable); // start from here
   if (drawable != null && drawable instanceof WeatherDrawable && isShown()) {
        ((WeatherDrawable) drawable).startAnimation();
    }
}

2.從ImageView的方法setImageDrawable(drawable)開(kāi)始找ViewDrawable的關(guān)系

/**
 * Sets a drawable as the content of this ImageView.
 *
 * @param drawable the Drawable to set, or {@code null}
 * to clear the content
 */
public void setImageDrawable(@Nullable Drawable drawable) {
    if (mDrawable != drawable) {
        mResource = 0;
        mUri = null;
        final int oldWidth = mDrawableWidth;
        final int oldHeight = mDrawableHeight;
        updateDrawable(drawable);
        if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
            requestLayout();
        }
        invalidate();
    }
}

3.先從updateDrawable(drawable)看起。起初被mDrawable騙了模她,從命名看這是ImageView的成員變量懂牧,updateDrawble(Drawable d)首先對(duì)其做了一些檢查不管僧凤。接著代碼就很明了,把傳進(jìn)來(lái)的Drawable對(duì)象賦給成員變量mDrawable旋膳。如果參數(shù)d不為空的話(huà)溺忧,那么設(shè)置d的Callback盯孙。

private void updateDrawable(Drawable d) {
    if (d != mRecycleableBitmapDrawable && mRecycleableBitmapDrawable != null) {
        mRecycleableBitmapDrawable.setBitmap(null);
    }
    if (mDrawable != null) {
        mDrawable.setCallback(null);// 
        unscheduleDrawable(mDrawable);
    }
    mDrawable = d;
    if (d != null) {
        d.setCallback(this);
        d.setLayoutDirection(getLayoutDirection());
        if (d.isStateful()) {
            d.setState(getDrawableState());
        }
        d.setVisible(getVisibility() == VISIBLE, true);
        d.setLevel(mLevel);
        mDrawableWidth = d.getIntrinsicWidth();
        mDrawableHeight = d.getIntrinsicHeight();
        applyImageTint();
        applyColorMod();
        configureBounds();
    } else {
        mDrawableWidth = mDrawableHeight = -1;
    }
}

4.繼續(xù)從d.setCallback(this);看下去振惰,以View對(duì)象新建一個(gè)弱引用new WeakReference<Callback>(cb)賦給Drawable對(duì)象的d的成員變量mCallback骑晶。

/**
 * Bind a {@link Callback} object to this Drawable.  Required for clients
 * that want to support animated drawables.
 *
 * @param cb The client's Callback implementation.
 *
 * @see #getCallback()
 */public final void setCallback(Callback cb) {
    mCallback = new WeakReference<Callback>(cb);
}

正如(https://www.zybuluo.com/linux1s1s/note/93075) 所說(shuō)的草慧,類(lèi)ImageView的父類(lèi)View實(shí)現(xiàn)了Drawable.Callback的接口漫谷。

public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
    private static final boolean DBG = false;
    /**
     * The logging tag used by this class with android.util.Log.
     */    protected static final String VIEW_LOG_TAG = "View";
    // ...此處省略了余下代碼

查看源碼也可以看到Drawable類(lèi)定義了該接口

public abstract class Drawable {

    // 此處省略了無(wú)關(guān)代碼

    private WeakReference<Callback> mCallback = null;// <---- HERE!

    // 此間省略了無(wú)關(guān)代碼

    /**
     * Implement this interface if you want to create an animated drawable that
     * extends {@link android.graphics.drawable.Drawable Drawable}.
     * Upon retrieving a drawable, use
     * {@link Drawable#setCallback(android.graphics.drawable.Drawable.Callback)}
     * to supply your implementation of the interface to the drawable; it uses
     * this interface to schedule and execute animation changes.
     */public static interface Callback {
        // 此處省略了注釋
        public void invalidateDrawable(Drawable who);

        // 此處省略了注釋
        public void scheduleDrawable(Drawable who, Runnable what, long when);

        // 此處省略了注釋
        public void unscheduleDrawable(Drawable who, Runnable what);
}

Drawable沒(méi)有實(shí)現(xiàn)任何與用戶(hù)的互動(dòng)碟婆,而完全是交給View,誠(chéng)如Google文檔(https://developer.android.com/reference/android/graphics/drawable/Drawable.html) 描述的惕稻,ViewDrawable各司其職。

A Drawable is a general abstraction for "something that can be drawn." Most often you will deal with Drawable as the type of resource retrieved for drawing things to the screen; the Drawable class provides a generic API for dealing with an underlying visual resource that may take a variety of forms. Unlike a View
, a Drawable does not have any facility to receive events or otherwise interact with the user.

二公给、Drawable Call

Google官方文檔描述DrawableinvalidateSelf()如下:

invalidateSelf()
Use the current Drawable.Callback
implementation to have this Drawable redrawn.

1.查看DrawableinvalidateSelf()源碼如下淌铐。
所以當(dāng)Drawable內(nèi)部或者其對(duì)象調(diào)用invalidateSelf()的時(shí)候匣沼,便以Drawable對(duì)象自身為參數(shù),讓類(lèi)ImageView來(lái)調(diào)用實(shí)現(xiàn)了Drawable.CallbackinvalidateDrawable(Drawable who)方法加叁。

/**
 * Use the current {@link Callback} implementation to have this Drawable
 * redrawn.  Does nothing if there is no Callback attached to the
 * Drawable.
 *
 * @see Callback#invalidateDrawable
 * @see #getCallback()
 * @see #setCallback(android.graphics.drawable.Drawable.Callback)
 */
public void invalidateSelf() {
    final Callback callback = getCallback();
    if (callback != null) {
        callback.invalidateDrawable(this);
    }
}

2.查看View是如何實(shí)現(xiàn)的invalidateDrawable(Drawable who)它匕。
如果一切“正辰讶希”扑浸,即參數(shù)dr等于成員變量mDrawable且不為空,那么最終會(huì)調(diào)用invalidate()方法。

@Override
public void invalidateDrawable(Drawable dr) {
    if (dr == mDrawable) {
        if (dr != null) {
            // update cached drawable dimensions if they've changed
            final int w = dr.getIntrinsicWidth();
            final int h = dr.getIntrinsicHeight();
            if (w != mDrawableWidth || h != mDrawableHeight) {
                mDrawableWidth = w;
                mDrawableHeight = h;
            }
        }
        /* we invalidate the whole view in this case because it's very
         * hard to know where the drawable actually is. This is made
         * complicated because of the offsets and transformations that
         * can be applied. In theory we could get the drawable's bounds
         * and run them through the transformation and offsets, but this
         * is probably not worth the effort.
         */
        invalidate();
    } else {
        super.invalidateDrawable(dr);
    }
}

3.最后invalidate()可以參考(https://www.zybuluo.com/linux1s1s/note/93075)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末榴鼎,一起剝皮案震驚了整個(gè)濱河市晚唇,隨后出現(xiàn)的幾起案子哩陕,更是在濱河造成了極大的恐慌,老刑警劉巖葵礼,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸳粉,死亡現(xiàn)場(chǎng)離奇詭異园担,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)艰山,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)曙搬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人征讲,你說(shuō)我怎么就攤上這事橡娄⊥彀Γ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)塑顺。 經(jīng)常有香客問(wèn)我茬暇,道長(zhǎng)寡喝,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮格二,結(jié)果婚禮上劈彪,老公的妹妹穿的比我還像新娘。我一直安慰自己顶猜,他們只是感情好沧奴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著长窄,像睡著了一般滔吠。 火紅的嫁衣襯著肌膚如雪纲菌。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天疮绷,我揣著相機(jī)與錄音翰舌,去河邊找鬼。 笑死椅贱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的只冻。 我是一名探鬼主播庇麦,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼属愤!你這毒婦竟也來(lái)了女器?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤住诸,失蹤者是張志新(化名)和其女友劉穎驾胆,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贱呐,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡丧诺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奄薇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片驳阎。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖馁蒂,靈堂內(nèi)的尸體忽然破棺而出呵晚,到底是詐尸還是另有隱情,我是刑警寧澤沫屡,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布饵隙,位于F島的核電站,受9級(jí)特大地震影響沮脖,放射性物質(zhì)發(fā)生泄漏金矛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一勺届、第九天 我趴在偏房一處隱蔽的房頂上張望驶俊。 院中可真熱鬧,春花似錦免姿、人聲如沸饼酿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嗜湃。三九已至奈应,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間购披,已是汗流浹背杖挣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刚陡,地道東北人惩妇。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像筐乳,于是被迫代替她去往敵國(guó)和親歌殃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容