Android 事件分發(fā) 面試如何去談

Android 事件分發(fā)流程

事件分發(fā).jpeg

問題一:

面試中面試官常常會問到在項目中你的局部View 的刷新是如何處理成玫?

問題二:

面試中面試官常常會問到View組件中滑動沖突你是如何處理的?

答案就在下面

其實這個兩個問題的核心點就是要談到Androird事件分發(fā)機制

所以回答問題的核心思想就是通過 Activity => ViewGroup => View 的順序進行執(zhí)行事件分發(fā)乳规,然后通過調(diào)用 onTouchEvent() 方法進行事件的處理。我們在項目中一般會對View的點擊事件動作進行記錄處理如:
ACTION_DOWN: 第一個手指按下時
ACTION_MOVE:按住一點在屏幕上移動
ACTION_UP:最后一個手指抬起時
ACTION_CANCEL:當前的手勢被取消了
分情況進行操作阶界。

一般情況下遭笋,事件列都是從用戶按下(ACTION_DOWN)的那一刻產(chǎn)生的,不得不提到欢峰,三個非常重要的與事件相關(guān)的方法。

dispatchTouchEvent()

onTouchEvent()

onInterceptTouchEvent()

Activity 的事件分發(fā)機制分析

在Activity 層中dispatchTouchEvent() 是負責事件分發(fā)的涨共。當點擊事件產(chǎn)生后纽帖,事件首先會傳遞給當前的 Activity,這會調(diào)用 Activity 的 dispatchTouchEvent() 方法举反,我們來看看源碼中是怎么處理的懊直。


圖片.png

注意圖中,我增加了一些注釋火鼻,便于我們更加方便的理解室囊,由于我們一般產(chǎn)生點擊事件都是 MotionEvent.ACTION_DOWN,所以一般都會調(diào)用到 onUserInteraction() 這個方法魁索。我們不妨來看看都做了什么融撞。


圖片.png

從圖上可以看到,這個方法實現(xiàn)是空的粗蔚,不過我們可以從注釋和其他途徑可以了解到尝偎,該方法主要的作用是實現(xiàn)屏保功能,并且當此 Activity 在棧頂?shù)臅r候,觸屏點擊 Home致扯、Back肤寝、Recent 鍵等都會觸發(fā)這個方法。
再來看看第二個 if語句抖僵,getWindow().superDispatchTouchEvent()鲤看,getWindow() 明顯是獲取 Window,由于 Window 是一個抽象類裆针,所以我們能拿到其子類 PhoneWindow刨摩,我們直接看看 PhoneWindows.superDispatchTouchEvent() 到底做了什么操作寺晌。
圖片.png

直接調(diào)用了 DecorView 的 superDispatchTrackballEvent() 方法世吨。DecorView 繼承于 FrameLayout,作為頂層 View呻征,是所有界面的父類耘婚。而 FrameLayout 作為 ViewGroup 的子類,所以直接調(diào)用了 ViewGroup 的 dispatchTouchEvent()陆赋。

ViewGroup 的事件分發(fā)機制分析

我們通過查看 ViewGroup 的 dispatchTouchEvent() 可以發(fā)現(xiàn)沐祷。


圖片.png

注意其中紅框里面的代碼,看注釋也能知道攒岛,定義了一個 boolean 值變量 intercept 來表示是否要攔截事件赖临。
其中采用到了 onInterceptTouchEvent(ev) 對 intercept 進行賦值。大多數(shù)情況下灾锯,onInterceptTouchEvent() 返回值為 false兢榨,但我們完全可以通過重寫 onInterceptTouchEvent(ev) 來改變它的返回值,不妨繼續(xù)往下看顺饮,我們后面對這個 intercept 做了什么處理吵聪。


圖片.png

暫時忽略 判斷的 canceled,該值同樣大多數(shù)時候都返回 false兼雄,所以當我們沒有重寫 onInterceptTouchEvent() 并使它的返回值為 true 時吟逝,一般情況下都是可以進入到該方法的。
繼續(xù)閱讀源碼可以發(fā)現(xiàn)赦肋,里面做了一個 For 循環(huán)块攒,通過倒序遍歷 ViewGroup 下面的所有子 View,然后一個一個判斷點擊位置是否是該子 View 的布局區(qū)域佃乘,當然還有一些其他的通過上面源碼簡單的閱讀可以總結(jié)如下:

View 的事件分發(fā)機制分析

ViewGroup 說到底還是一個 View囱井,所以我們不得不繼續(xù)看看 View 的 dispatchTouchEvent()。


圖片.png

紅框中的三個條件恕稠,第一個我就不用說了琅绅。
(mViewFlags & ENABLED_MASK) == ENABLED該條件是判斷當前點擊的控件是否為 enable劫灶,但由于基本 View 都是 enable 的邮辽,所以這個條件基本都返回 true请敦。
mOnTouchListener.onTouch(this, event)
即我們調(diào)用 setOnTouchListener() 時必須覆蓋的方法 onTouch() 的返回值秃嗜。
從上述的分析,終于知道「onTouch() 方法優(yōu)先級高于 onTouchEvent(event) 方法」是怎么來的了吧澎羞。
再來看看 onTouchEvent()


圖片.png

從上面的代碼可以明顯地看到髓绽,只要 View 的 CLICKABLE 和 LONG_CLICKABLE 有一個為 true,那么 onTouchEvent() 就會返回 true 消耗這個事件妆绞。CLICKABLE 和 LONG_CLICKABLE 代表 View 可以被點擊和長按點擊顺呕,我們通常都會采用 setOnClickListener() 和 setOnLongClickListener() 做設(shè)置。接著在 ACTION_UP 事件中會調(diào)用 performClick() 方法括饶,我們看看都做了什么株茶。
圖片.png

從截圖中可以看到,如果 mOnClickListener 不為空图焰,那么它的 onClick() 方法就會調(diào)用启盛。

總結(jié)

需要總結(jié)的小點:
1.Android 事件分發(fā)總是遵循 Activity => ViewGroup => View 的傳遞順序;
2.onTouch() 執(zhí)行總優(yōu)先于 onClick()
3.Activity 的事件分發(fā)示意圖


圖片.png

4.ViewGroup 事件分發(fā)示意圖


圖片.png

5.View 的事件分發(fā)示意圖
圖片.png

6.事件分發(fā)工作流程總結(jié)
圖片.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末技羔,一起剝皮案震驚了整個濱河市僵闯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌藤滥,老刑警劉巖鳖粟,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拙绊,居然都是意外死亡向图,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門时呀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來张漂,“玉大人,你說我怎么就攤上這事谨娜『皆埽” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵趴梢,是天一觀的道長漠畜。 經(jīng)常有香客問我,道長坞靶,這世上最難降的妖魔是什么憔狞? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮彰阴,結(jié)果婚禮上瘾敢,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好簇抵,可當我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布庆杜。 她就那樣靜靜地躺著,像睡著了一般碟摆。 火紅的嫁衣襯著肌膚如雪晃财。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天典蜕,我揣著相機與錄音断盛,去河邊找鬼。 笑死愉舔,一個胖子當著我的面吹牛钢猛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屑宠,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼厢洞,長吁一口氣:“原來是場噩夢啊……” “哼仇让!你這毒婦竟也來了典奉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤丧叽,失蹤者是張志新(化名)和其女友劉穎卫玖,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體踊淳,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡假瞬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了迂尝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脱茉。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖垄开,靈堂內(nèi)的尸體忽然破棺而出琴许,到底是詐尸還是另有隱情,我是刑警寧澤溉躲,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布榜田,位于F島的核電站,受9級特大地震影響锻梳,放射性物質(zhì)發(fā)生泄漏箭券。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一疑枯、第九天 我趴在偏房一處隱蔽的房頂上張望辩块。 院中可真熱鬧,春花似錦、人聲如沸废亭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滔以。三九已至捉腥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間你画,已是汗流浹背抵碟。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坏匪,地道東北人拟逮。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像适滓,于是被迫代替她去往敵國和親敦迄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,585評論 2 359

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