android關(guān)于dispatchTouchEvent和onTouchEvent的源碼實(shí)驗(yàn)分析

(一)源碼調(diào)試:設(shè)置build中編譯版本為23(6.0);必須使用google官方6.0系統(tǒng)手機(jī)(如Nexus系列且安裝6.0系統(tǒng))或者使用虛擬機(jī)(配置也是Nexus6.0系統(tǒng))。這樣要求是為了運(yùn)行設(shè)備和編譯器編譯使用同一個版本安疗,而且都是google官方版本抄邀,在調(diào)試打斷點(diǎn)的時候就不會出現(xiàn)斷點(diǎn)行號和源碼行號對不上的問題了掠兄。切記調(diào)試條件:

1喂击、編譯版本和測試機(jī)版本必須相同剂癌。

2、測試機(jī)使用Google官方版本惭等,Nexus系列或者虛擬機(jī)珍手。(使用其他品牌真機(jī)調(diào)試办铡,因?yàn)槭謾C(jī)框架層是被定制修改過的辞做,所以會和編譯器上的源碼對不上)

(二)源碼使用的是6.0系統(tǒng)源碼。

(三)

代碼結(jié)構(gòu):A繼承自RelativeLayout寡具;B繼承自RelativeLayout秤茅;C繼承自TextView;都重寫dispatchTouchEvent和onTouchEvent兩個方法并打入Log童叠;

測試代碼段:ViewGroup類dispatchTouchEvent方法框喳。

斷點(diǎn)代碼行數(shù):ViewGroup類课幕,斷點(diǎn)1:2197行,斷點(diǎn)2:2238行五垮。

注意:以下的驗(yàn)證和猜想都是針對Down動作的乍惊,不涉及move和up等。

已驗(yàn)證過程:假設(shè)A包含B放仗,B包含C润绎,所有dispatchTouchEvent和onTouchEvent返回默認(rèn)值,點(diǎn)擊C诞挨,會先調(diào)用A的dispatchTouchEvent莉撇,在斷點(diǎn)1處停留,斷點(diǎn)1處調(diào)用方法dispatchTransformedTouchEvent惶傻,它的參數(shù)child就是B棍郎,這個方法會使B調(diào)用自己的dispatchTouchEvent;又在斷點(diǎn)1處停留银室,調(diào)用dispatchTransformedTouchEvent,它的參數(shù)child是C涂佃,方法中C會調(diào)用自己的dispatchTouchEvent;C是一個View蜈敢,View的dispatchTouchEvent方法會調(diào)用自己的onTouchEvent并返回false巡李。注意,到此扶认,A》B》C的dispatchTouchEvent調(diào)用就完畢了侨拦,并且C執(zhí)行了返回,后面就是C》B》A的onTouchEvent返回過程了辐宾,這就是個遞歸狱从。繼續(xù)斷點(diǎn),B在斷點(diǎn)1處得到C的返回值叠纹,能夠繼續(xù)執(zhí)行了季研,并且在B的斷點(diǎn)2處停留,斷點(diǎn)2處會再次調(diào)用B的dispatchTransformedTouchEvent方法誉察,并且參數(shù)child為null与涡,方法就會調(diào)用super.dispatchTouchEvent(也就是調(diào)用B的父類View的dispatchTouchEvent),然后就會調(diào)用B的onTouchEvent方法并返回false持偏。這樣一來A在斷點(diǎn)1處有了返回值就可以繼續(xù)執(zhí)行了驼卖,并且在A的端點(diǎn)2處停留,端點(diǎn)2處會再次調(diào)用A的dispatchTransformedTouchEvent方法鸿秆,并且參數(shù)child為null酌畜,方法會調(diào)用super.dispatchTouchEvent,方法中就調(diào)用A的onTouchEvent卿叽。至此桥胞,就完成了C》B》A的onTouchEvent回溯過程了恳守。做一個形象的比喻:Android的觸碰過程就像走樓梯,由十層一層一層的走到一層贩虾,在一層走到大廈另一邊的樓梯催烘,再由一層一層一層走到十層。默認(rèn)情況下你是不可以直接由7層走到另一側(cè)的樓梯的缎罢。

猜想一:在B的dispatchTouchEvent直接返回true颗圣,則A在斷點(diǎn)1處停留,調(diào)用dispatchTransformedTouchEvent方法屁使,參數(shù)child是B在岂,B調(diào)用自己的dispatchTouchEvent并直接返回true。則A在斷點(diǎn)1處有了返回true可以繼續(xù)執(zhí)行蛮寂,然后就在A的斷點(diǎn)2處停留蔽午,最后會調(diào)用到A的onTouchEvent

猜想一結(jié)果:真實(shí)的運(yùn)行結(jié)果是執(zhí)行了A的dispatchTouchEvent和B的dispatchTouchEvent就結(jié)束了,并沒有執(zhí)行A的onTouchEvent酬蹋。

猜想一分析:猜想和結(jié)果的出入就是最后是否調(diào)用了A的onTouchEvent及老,看斷點(diǎn)1處的代碼:

A執(zhí)行dispatchTransformedTouchEvent,也就是想B分發(fā)范抓,執(zhí)行B的dispatchTouchEvent骄恶,根據(jù)上面的猜想B的dispatchTouchEvent會直接返回true,if成立匕垫,然后就會執(zhí)行2213和2214行僧鲁,2214行給標(biāo)志位alreadyDispatchedToNewTouchTarget置為true,2213行執(zhí)行addTouchTarget方法并把返回值置給newTouchTarget:

在addTouchTarget方法中給mFirstTouchTarget賦值并把一個相同值返回付給了newTouchTarget象泵。

再回到流程中看寞秃,B的dispatchTouchEvent直接返回true,A的dispatchTransformedTouchEvent有了返回值就可以繼續(xù)執(zhí)行代碼偶惠,執(zhí)行到斷點(diǎn)2處又碰到一個if判斷:

由斷點(diǎn)1處分析可知春寿,mFirstTouchTarget等于newTouchTarget且不等于null,所有if不成立(跳過了回溯過程中調(diào)用dispatchTransformedTouchEvent的第一次機(jī)會)忽孽,執(zhí)行2243-2270行绑改,其中2249行又遇到一個if判斷,判斷條件alreadyDispatchedToNewTouchTarget等于true兄一、target也的確等于newTouchTarget(見前面)厘线,if成立(跳過了回溯過程中調(diào)用dispatchTransformedTouchEvent的第二次機(jī)會)。在dispatchTouchEvent直接返回true而導(dǎo)致的后續(xù)過程中我們可以看到瘾腰,我們根本沒有機(jī)會運(yùn)行到dispatchTransformedTouchEvent方法皆的,也就沒有機(jī)會執(zhí)行到onTouchEvent方法覆履。

猜想二:在B的onTouchEvent直接返回true蹋盆,則完整執(zhí)行dispatchTouchEvent的A》B》C過程费薄,onTouchEvent方法的回溯過程只執(zhí)行到B就結(jié)束。

猜想二結(jié)果:點(diǎn)擊C栖雾,執(zhí)行過程:A的dispatchTouchEvent》B的dispatchTouchEvent》C的dispatchTouchEvent》C的onTouchEvent》B的onTouchEvent結(jié)束楞抡。與猜想一致。

下面是對UP事件的分析:

在猜想二驗(yàn)證結(jié)果時析藕,程序的log除了顯示上面的“猜想二結(jié)果”召廷,還顯示了一套UP事件的傳遞log:A的dispatchTouchEvent》B的dispatchTouchEvent》B的onTouchEvent結(jié)束。

也就是說目標(biāo)是要從三樓左側(cè)的樓梯去到二樓右側(cè)的樓梯账胧。D君(Down事件)先從三樓左側(cè)樓梯一直下到一樓竞慢,穿過一樓樓層到達(dá)一樓右側(cè)樓梯,在爬到二樓右側(cè)樓梯治泥,到達(dá)筹煮!U君(UP事件)從三樓左側(cè)樓梯下到二樓,然后直接穿過二樓樓層到達(dá)二樓右側(cè)樓梯居夹,到達(dá)0芰省!

源碼上說up流程的成因只需要明白一點(diǎn):down流程之所以會有dispatchTouchEvent下發(fā)和onTouchEvent回溯兩個對稱流程准脂,是因?yàn)榇a層次上有斷點(diǎn)1和斷點(diǎn)2兩個地方能夠執(zhí)行兩次dispatch方法(第一次目的是為了能夠調(diào)用dispatchTouchEvent劫扒,第二次目的是為了能夠調(diào)用onTouchEvent)。而對于up流程狸膏,在源碼中斷點(diǎn)1是包含在一個if語句中(2143-2145):

if(actionMasked == MotionEvent.ACTION_DOWN || (split && actionMasked == MotionEvent.ACTION_POINTER_DOWN) || actionMasked == MotionEvent.ACTION_HOVER_MOVE)

可以看到沟饥,只有down和move事件能夠執(zhí)行斷點(diǎn)1處的dispatch,所以up就只能執(zhí)行一次斷點(diǎn)2處的dispatch了,緊接著我們再來看一遍斷點(diǎn)2代碼段:

仔細(xì)看湾戳,無論if是否成立闷板,都會調(diào)用dispatchTransformedTouchEvent方法,不同的是方法的第三個參數(shù)child不同院塞,下面直接給出結(jié)論:當(dāng)mFirstTouchTarget為null是dispatchTransformedTouchEvent的child傳null遮晚,則調(diào)用當(dāng)前類的onTouchEvent方法;反之拦止,child傳子View县遣,則調(diào)用子View的dispatchTouchEvent方法。

這個結(jié)論的關(guān)鍵點(diǎn)是mFirstTouchTarget是否為null汹族,當(dāng)它不為null時dispatchTouchEvent繼續(xù)下放萧求,當(dāng)它為null時調(diào)用同級的onTouchEvent并開始回溯。

那mFirstTouchTarget是在哪里設(shè)置的呢顶瞒?mFirstTouchTarget只有在down過程中才會被設(shè)置夸政,具體參考猜想一中的分析。我們可以想象得到榴徐,在down過程中守问,當(dāng)B的onTouchEvent返回true匀归,調(diào)用它的A中mFirstTouchTarget就會被賦值(A的父集們的mFirstTouchTarget都會遞歸被賦值),而B中的mFirstTouchTarget還是保持為null耗帕。有了這個結(jié)果穆端,在up過程中到了B的斷點(diǎn)2處,mFirstTouchTarget為null仿便,就會調(diào)用同級的onTouchEvent体啰,這樣就實(shí)現(xiàn)了從三樓左側(cè)樓梯下到二樓直接穿過樓層到達(dá)二樓右側(cè)樓梯。

沒有實(shí)踐調(diào)試的過程嗽仪,看起來絕對是似是而非似懂非懂的荒勇,所以Debug源碼才是最終理解的正途!N偶帷枕屉!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鲤氢,隨后出現(xiàn)的幾起案子搀擂,更是在濱河造成了極大的恐慌,老刑警劉巖卷玉,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哨颂,死亡現(xiàn)場離奇詭異,居然都是意外死亡相种,警方通過查閱死者的電腦和手機(jī)威恼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寝并,“玉大人箫措,你說我怎么就攤上這事〕牧剩” “怎么了斤蔓?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長镀岛。 經(jīng)常有香客問我弦牡,道長,這世上最難降的妖魔是什么漂羊? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任驾锰,我火速辦了婚禮,結(jié)果婚禮上走越,老公的妹妹穿的比我還像新娘椭豫。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布赏酥。 她就那樣靜靜地躺著喳整,像睡著了一般。 火紅的嫁衣襯著肌膚如雪今缚。 梳的紋絲不亂的頭發(fā)上算柳,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天低淡,我揣著相機(jī)與錄音姓言,去河邊找鬼。 笑死蔗蹋,一個胖子當(dāng)著我的面吹牛何荚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播猪杭,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼餐塘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了皂吮?” 一聲冷哼從身側(cè)響起戒傻,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜂筹,沒想到半個月后需纳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡艺挪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年不翩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片麻裳。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡口蝠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出津坑,到底是詐尸還是另有隱情妙蔗,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布疆瑰,位于F島的核電站灭必,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏乃摹。R本人自食惡果不足惜禁漓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望孵睬。 院中可真熱鬧播歼,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至烁试,卻和暖如春雇初,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背减响。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工靖诗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人支示。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓刊橘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親颂鸿。 傳聞我的和親對象是個殘疾皇子促绵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

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