事件分發(fā)常見Interview questions

1.ViewGroup中的mFirstTouchTarget是一個(gè)什么東西狠裹,它有什么作用捣卤?

在ViewGroup中有一個(gè)類型為TouchTrarget的mFirstTouchTarget的成員變量,它是用來保存消費(fèi)事件的子View的信息的理疙。代碼如下:

private static final class TouchTarget {
        @UnsupportedAppUsage
        public View child;
        public TouchTarget next;
       // ...省略無關(guān)代碼
    }

可以看到TouchTarget內(nèi)部保存了一個(gè)View和一個(gè)類型為TouchTarget的next成員變量,也就是說TouchTarget是一個(gè)鏈表結(jié)構(gòu)。為什么是鏈表結(jié)構(gòu)呢悯舟?主要是因?yàn)锳ndroid系統(tǒng)是支持多點(diǎn)觸控的,所以TouchTarget設(shè)計(jì)成了鏈表砸民。

設(shè)計(jì)mFirstTouchTarget的目的是為了避免在所有的事件序列中都去遞歸查找要消費(fèi)事件的View抵怎,只需要在ACTION_DOWN中遞歸查找消費(fèi)的View,并將View封裝后賦值為mFirstTouchTarget岭参,避免了后續(xù)一系列事件的查找反惕。

mFirstTouchTarget會(huì)在ACTION_DOWN的時(shí)候被賦值,查找是否有能夠消費(fèi)事件的子View演侯,如果有則將這個(gè)View包裝成TouchTarget賦值給mFirstTouchTarget姿染,否則mFirstTouchTarget為null。

接下來的一系列ACTION_MOVE事件都會(huì)根據(jù)mFirstTouchTarget是否為null和onInterceptTouchEvent來判斷是否要攔截事件秒际。所以mFirstTouchTarget在事件分發(fā)的流程中占了非常重要的作用悬赏。

2.如果在ViewGroup中攔截了ACTION_DOWN事件會(huì)怎樣?

首先來看ViewGroup的dispatchTouchEvent方法的偽代碼:

// ViewGroup
public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean handled = false;
        final boolean intercepted;
        if (actionMasked == MotionEvent.ACTION_DOWN
                || mFirstTouchTarget != null) {
             // 調(diào)用自身的onInterceptTouchEvent方法來判斷是否攔截事件
            intercepted = onInterceptTouchEvent(ev);
        } else {
            intercepted = true;
        }
        // 如果在ACTION_DOWN中攔截了事件娄徊,那么intercepted恒為true闽颇,則無法給mFirstTouchTarget賦值
        if (!canceled && !intercepted) {
            mFirstTouchTarget = findConsumeChild(this);
        }
        if (mFirstTouchTarget == null) {  
            // 則調(diào)用自身的dispatchTouchEvent方法分發(fā)事件             
            handled = super.dispatchTouchEvent(event);
        } else{
            // 則調(diào)用子View的dispatchTouchEvent方法
            handled = mFirstTouchTarget.child.dispatchTouchEvent(event);
        }
        return handled;
    }

從上面的代碼中可以看到,如果在onInterceptTouchEvent方法中攔截ACTION_DOWN事件寄锐,則intercepted為true兵多,而intercepted為true直接導(dǎo)致了mFirstTouchTarget無法被賦值。

接下來橄仆,一系列ACTION_MOVE以及ACTION_UP等事件都無法再調(diào)用onInterceptTouchEvent方法剩膘,也就是intercepted恒為true,且mFirstTouchTarget恒為null沿癞。

再往下援雇,由于mFirstTouchTarget恒為null,就導(dǎo)致了所有的Motion事件(也包括ACTION_DOWN事件)只能交由自身處理椎扬,無法再將事件分發(fā)給子View惫搏。

這一點(diǎn)在事件分發(fā)流程中非常重要具温,通過Down事件確定了要處理該事件的View,接下來所有的Move事件序列就不會(huì)再走遞歸筐赔,而是直接交給這個(gè)View來

3.為什么設(shè)置了onTouchListener后onClickListener不會(huì)被調(diào)用铣猩?

// View
public boolean dispatchTouchEvent(MotionEvent event) {
            //noinspection SimplifiableIfStatement
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }

        return result;
    }

在View的dispatchTouchEvent中如果li.mOnTouchListener不為null,則調(diào)用li.mOnTouchListener.onTouch茴丰,而如果li.mOnTouchListener.onTouch返回了true达皿,則下邊的onTouchEvent就不會(huì)被調(diào)用,而onClickListener就是在onTouchEvent方法中才被調(diào)用的贿肩。

// 偽代碼
public boolean onTouchEvent(MotionEvent event) {
    public boolean onTouchEvent(MotionEvent event) {
        case MotionEvent.ACTION_UP:
            li.mOnClickListener.onClick(this);
        break;
    }
}

4.為什么一個(gè)View設(shè)置了setOnTouchListener會(huì)有提示沒有引用performClick方法的警告峦椰?

當(dāng)你添加了一些點(diǎn)擊操作,例如像setOnClickListener這樣的汰规,它會(huì)調(diào)用performClick才可以完成onClick方法的調(diào)用汤功,但你重寫了onTouch,就有可能使得performClick沒有被調(diào)用溜哮,這樣這些點(diǎn)擊操作就沒辦法完成了滔金,所以就會(huì)有了這個(gè)警告。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末茂嗓,一起剝皮案震驚了整個(gè)濱河市餐茵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌述吸,老刑警劉巖忿族,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蝌矛,居然都是意外死亡肠阱,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門朴读,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人走趋,你說我怎么就攤上這事衅金。” “怎么了簿煌?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)姨伟。 經(jīng)常有香客問我惩琉,道長(zhǎng),這世上最難降的妖魔是什么夺荒? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任瞒渠,我火速辦了婚禮良蒸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伍玖。我一直安慰自己嫩痰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布窍箍。 她就那樣靜靜地躺著串纺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪椰棘。 梳的紋絲不亂的頭發(fā)上纺棺,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音邪狞,去河邊找鬼祷蝌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛外恕,可吹牛的內(nèi)容都是我干的杆逗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼鳞疲,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼罪郊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起尚洽,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤悔橄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后腺毫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體癣疟,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年潮酒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了睛挚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡急黎,死狀恐怖扎狱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情勃教,我是刑警寧澤淤击,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站故源,受9級(jí)特大地震影響污抬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绳军,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一印机、第九天 我趴在偏房一處隱蔽的房頂上張望矢腻。 院中可真熱鬧,春花似錦耳贬、人聲如沸踏堡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽顷蟆。三九已至,卻和暖如春腐魂,著一層夾襖步出監(jiān)牢的瞬間帐偎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工蛔屹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留削樊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓兔毒,卻偏偏與公主長(zhǎng)得像漫贞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子育叁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

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