日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

图解 Android 事件分发机制

發(fā)布時間:2023/12/20 Android 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图解 Android 事件分发机制 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

首發(fā)原文:http://mp.weixin.qq.com/s?__biz=MzI0MjE3OTYwMg==&mid=2649548149&idx=1&sn=709149df682c7d3a6e453c9ef0626a1f&chksm=f1180e08c66f871eb2e7e39e057a5b090214fd71adcd98aa36b3d7fcecf77ad5d08138c50131#rd


在Android開發(fā)中,事件分發(fā)機(jī)制是一塊Android比較重要的知識體系,了解并熟悉整套的分發(fā)機(jī)制有助于更好的分析各種點擊滑動失效問題,更好去擴(kuò)展控件的事件功能和開發(fā)自定義控件,同時事件分發(fā)機(jī)制也是Android面試必問考點之一,如果你能把下面的一些事件分發(fā)圖當(dāng)場畫出來肯定加分不少。廢話不多說,總結(jié)一句:事件分發(fā)機(jī)制很重要

Android 事件分發(fā)流

關(guān)于Android 事件分發(fā)機(jī)制網(wǎng)上的博文很多,但是很多都是寫個Demo然后貼一下輸出的Log或者拿源碼分析,然后一堆的注釋和說明,如果用心的去看肯定是收獲不少但是確實很難把整個流程說清和記住。曾經(jīng)也是拼命想記住整個流程,但是一段時間又忘了,最后覺得分析這種問題和事件流的走向,一張圖來解釋和說明會清晰很多,下面我根據(jù)畫的一張事件分發(fā)流程圖,說明的事件從用戶點擊之后,在不同函數(shù)不同返回值的情況的最終走向。


圖 1.

注:

  • 仔細(xì)看的話,圖分為3層,從上往下依次是Activity、ViewGroup、View

  • 事件從左上角那個白色箭頭開始,由Activity的dispatchTouchEvent做分發(fā)

  • 箭頭的上面字代表方法返回值,(return true、return false、return super.xxxxx(),super 的意思是調(diào)用父類實現(xiàn)。

  • dispatchTouchEvent和 onTouchEvent的框里有個【true---->消費(fèi)】的字,表示的意思是如果方法返回true,那么代表事件就此消費(fèi),不會繼續(xù)往別的地方傳了,事件終止。

  • 目前所有的圖的事件是針對ACTION_DOWN的,對于ACTION_MOVE和ACTION_UP我們最后做分析。

  • 之前圖中的Activity 的dispatchTouchEvent 有誤(圖已修復(fù)),只有return ?super.dispatchTouchEvent(ev) 才是往下走,返回true 或者 false 事件就被消費(fèi)了(終止傳遞)。

仔細(xì)看整個圖,我們得出事件流 走向的幾個結(jié)論(希望讀者專心的看下圖 1,多看幾遍,腦子有比較清晰的概念。)
1、如果事件不被中斷,整個事件流向是一個類U型圖,我們來看下這張圖,可能更能理解U型圖的意思。


圖 2.

所以如果我們沒有對控件里面的方法進(jìn)行重寫或更改返回值,而直接用super調(diào)用父類的默認(rèn)實現(xiàn),那么整個事件流向應(yīng)該是從Activity---->ViewGroup--->View 從上往下調(diào)用dispatchTouchEvent方法,一直到葉子節(jié)點(View)的時候,再由View--->ViewGroup--->Activity從下往上調(diào)用onTouchEvent方法。

2、dispatchTouchEvent 和 onTouchEvent 一旦return true,事件就停止傳遞了(到達(dá)終點)(沒有誰能再收到這個事件)。看下圖中只要return true事件就沒再繼續(xù)傳下去了,對于return true我們經(jīng)常說事件被消費(fèi)了,消費(fèi)了的意思就是事件走到這里就是終點,不會往下傳,沒有誰能再收到這個事件了


圖 3.


3、dispatchTouchEvent 和 onTouchEvent return false的時候事件都回傳給父控件的onTouchEvent處理。


圖 4.


看上圖深藍(lán)色的線,對于返回false的情況,事件都是傳給父控件onTouchEvent處理。

  • 對于dispatchTouchEvent 返回 false 的含義應(yīng)該是:事件停止往子View傳遞和分發(fā)同時開始往父控件回溯(父控件的onTouchEvent開始從下往上回傳直到某個onTouchEvent return true),事件分發(fā)機(jī)制就像遞歸,return false 的意義就是遞歸停止然后開始回溯。

  • 對于onTouchEvent return false 就比較簡單了,它就是不消費(fèi)事件,并讓事件繼續(xù)往父控件的方向從下往上流動。

4、dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent
ViewGroup 和View的這些方法的默認(rèn)實現(xiàn)就是會讓整個事件安裝U型完整走完,所以 return super.xxxxxx() 就會讓事件依照U型的方向的完整走完整個事件流動路徑),中間不做任何改動,不回溯、不終止,每個環(huán)節(jié)都走到。


Paste_Image.png


所以如果看到方法return super.xxxxx() 那么事件的下一個流向就是走U型下一個目標(biāo),稍微記住上面這張圖,你就能很快判斷出下一個走向是哪個控件的哪個函數(shù)。
5、onInterceptTouchEvent 的作用


圖 5.

Intercept 的意思就攔截,每個ViewGroup每次在做分發(fā)的時候,問一問攔截器要不要攔截(也就是問問自己這個事件要不要自己來處理)如果要自己處理那就在onInterceptTouchEvent方法中 return true就會交給自己的onTouchEvent的處理,如果不攔截就是繼續(xù)往子控件往下傳。默認(rèn)是不會去攔截的,因為子View也需要這個事件,所以onInterceptTouchEvent攔截器return super.onInterceptTouchEvent()和return false是一樣的,是不會攔截的,事件會繼續(xù)往子View的dispatchTouchEvent傳遞

6、ViewGroup 和View 的dispatchTouchEvent方法返回super.dispatchTouchEvent()的時候事件流走向。


圖 6

首先看下ViewGroup 的dispatchTouchEvent,之前說的return true是終結(jié)傳遞。return false 是回溯到父View的onTouchEvent,然后ViewGroup怎樣通過dispatchTouchEvent方法能把事件分發(fā)到自己的onTouchEvent處理呢,return true和false 都不行,那么只能通過Interceptor把事件攔截下來給自己的onTouchEvent,所以ViewGroup dispatchTouchEvent方法的super默認(rèn)實現(xiàn)就是去調(diào)用onInterceptTouchEvent,記住這一點
那么對于View的dispatchTouchEvent return super.dispatchTouchEvent()的時候呢事件會傳到哪里呢,很遺憾View沒有攔截器。但是同樣的道理return true是終結(jié)。return false 是回溯會父類的onTouchEvent,怎樣把事件分發(fā)給自己的onTouchEvent 處理呢,那只能return super.dispatchTouchEvent,View類的dispatchTouchEvent()方法默認(rèn)實現(xiàn)就是能幫你調(diào)用View自己的onTouchEvent方法的。

說了這么多,不知道有說清楚沒有,我這邊最后總結(jié)一下:

  • 對于 dispatchTouchEvent,onTouchEvent,return true是終結(jié)事件傳遞。return false 是回溯到父View的onTouchEvent方法。

  • ViewGroup 想把自己分發(fā)給自己的onTouchEvent,需要攔截器onInterceptTouchEvent方法return true 把事件攔截下來。

  • ViewGroup 的攔截器onInterceptTouchEvent 默認(rèn)是不攔截的,所以return super.onInterceptTouchEvent()=return false;

  • View 沒有攔截器,為了讓View可以把事件分發(fā)給自己的onTouchEvent,View的dispatchTouchEvent默認(rèn)實現(xiàn)(super)就是把事件分發(fā)給自己的onTouchEvent。

ViewGroup和View 的dispatchTouchEvent 是做事件分發(fā),那么這個事件可能分發(fā)出去的四個目標(biāo)

注:------> 后面代表事件目標(biāo)需要怎么做。
1、 自己消費(fèi),終結(jié)傳遞。------->return true ;
? 2、 給自己的onTouchEvent處理-------> 調(diào)用super.dispatchTouchEvent()系統(tǒng)默認(rèn)會去調(diào)用 onInterceptTouchEvent,在onInterceptTouchEvent return true就會去把事件分給自己的onTouchEvent處理。
? 3、 傳給子View------>調(diào)用super.dispatchTouchEvent()默認(rèn)實現(xiàn)會去調(diào)用 onInterceptTouchEvent 在onInterceptTouchEvent return false,就會把事件傳給子類。
? 4、 不傳給子View,事件終止往下傳遞,事件開始回溯,從父View的onTouchEvent開始事件從下到上回歸執(zhí)行每個控件的onTouchEvent------->return false;
注: 由于View沒有子View所以不需要onInterceptTouchEvent 來控件是否把事件傳遞給子View還是攔截,所以View的事件分發(fā)調(diào)用super.dispatchTouchEvent()的時候默認(rèn)把事件傳給自己的onTouchEvent處理(相當(dāng)于攔截),對比ViewGroup的dispatchTouchEvent 事件分發(fā),View的事件分發(fā)沒有上面提到的4個目標(biāo)的第3點。

ViewGroup和View的onTouchEvent方法是做事件處理的,那么這個事件只能有兩個處理方式:

1、自己消費(fèi)掉,事件終結(jié),不再傳給誰----->return true;
? 2、繼續(xù)從下往上傳,不消費(fèi)事件,讓父View也能收到到這個事件----->return false;View的默認(rèn)實現(xiàn)是不消費(fèi)的。所以super==false。

ViewGroup的onInterceptTouchEvent方法對于事件有兩種情況:

1、攔截下來,給自己的onTouchEvent處理--->return true;
? ?2、不攔截,把事件往下傳給子View---->return false,ViewGroup默認(rèn)是不攔截的,所以super==false;

關(guān)于ACTION_MOVE 和 ACTION_UP

上面講解的都是針對ACTION_DOWN的事件傳遞,ACTION_MOVE和ACTION_UP在傳遞的過程中并不是和ACTION_DOWN 一樣,你在執(zhí)行ACTION_DOWN的時候返回了false,后面一系列其它的action就不會再得到執(zhí)行了。簡單的說,就是當(dāng)dispatchTouchEvent在進(jìn)行事件分發(fā)的時候,只有前一個事件(如ACTION_DOWN)返回true,才會收到ACTION_MOVE和ACTION_UP的事件。具體這句話很多博客都說了,但是具體含義是什么呢?我們來看一下下面的具體分析。

上面提到過了,事件如果不被打斷的話是會不斷往下傳到葉子層(View),然后又不斷回傳到Activity,dispatchTouchEvent 和 onTouchEvent 可以通過return true 消費(fèi)事件,終結(jié)事件傳遞,而onInterceptTouchEvent 并不能消費(fèi)事件,它相當(dāng)于是一個分叉口起到分流導(dǎo)流的作用,ACTION_MOVE和ACTION_UP 會在哪些函數(shù)被調(diào)用,之前說了并不是哪個函數(shù)收到了ACTION_DOWN,就會收到 ACTION_MOVE 等后續(xù)的事件的。
下面通過幾張圖看看不同場景下,ACTION_MOVE事件和ACTION_UP事件的具體走向并總結(jié)一下規(guī)律。

1、我們在ViewGroup1 的dispatchTouchEvent 方法返回true消費(fèi)這次事件

ACTION_DOWN 事件從(Activity的dispatchTouchEvent)--------> (ViewGroup1 的dispatchTouchEvent) 后結(jié)束傳遞,事件被消費(fèi)(如下圖紅色的箭頭代碼ACTION_DOWN 事件的流向)。

//打印日志 Activity | dispatchTouchEvent --> ACTION_DOWN ViewGroup1 | dispatchTouchEvent --> ACTION_DOWN---->消費(fèi)


在這種場景下ACTION_MOVE和ACTION_UP 將如何呢,看下面的打出來的日志

Activity | dispatchTouchEvent --> ACTION_MOVE ViewGroup1 | dispatchTouchEvent --> ACTION_MOVE----TouchEventActivity | dispatchTouchEvent --> ACTION_UP ViewGroup1 | dispatchTouchEvent --> ACTION_UP----

下圖中
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


2、我們在ViewGroup2 的dispatchTouchEvent 返回true消費(fèi)這次事件

Activity | dispatchTouchEvent --> ACTION_DOWN ViewGroup1 | dispatchTouchEvent --> ACTION_DOWNViewGroup1 | onInterceptTouchEvent --> ACTION_DOWNViewGroup2 | dispatchTouchEvent --> ACTION_DOWN---->消費(fèi)Activity | dispatchTouchEvent --> ACTION_MOVE ViewGroup1 | dispatchTouchEvent --> ACTION_MOVEViewGroup1 | onInterceptTouchEvent --> ACTION_MOVEViewGroup2 | dispatchTouchEvent --> ACTION_MOVE----TouchEventActivity | dispatchTouchEvent --> ACTION_UP ViewGroup1 | dispatchTouchEvent --> ACTION_UPViewGroup1 | onInterceptTouchEvent --> ACTION_UPViewGroup2 | dispatchTouchEvent --> ACTION_UP----

紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


Paste_Image.png

3、我們在View 的dispatchTouchEvent 返回true消費(fèi)這次事件
這個我不就畫圖了,效果和在ViewGroup2 的dispatchTouchEvent return true的差不多,同樣的收到ACTION_DOWN 的dispatchTouchEvent函數(shù)都能收到 ACTION_MOVE和ACTION_UP。
所以我們就基本可以得出結(jié)論如果在某個控件的dispatchTouchEvent 返回true消費(fèi)終結(jié)事件,那么收到ACTION_DOWN 的函數(shù)也能收到 ACTION_MOVE和ACTION_UP。

4、我們在View 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


5、我們在ViewGroup 2 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向



6、我們在ViewGroup 1 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


7、我們在Activity 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


8、我們在View的dispatchTouchEvent 返回false并且Activity 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


9、我們在View的dispatchTouchEvent 返回false并且ViewGroup 1 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


10、我們在View的dispatchTouchEvent 返回false并且在ViewGroup 2 的onTouchEvent 返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


11、我們在ViewGroup2的dispatchTouchEvent 返回false并且在ViewGroup1 的onTouchEvent返回true消費(fèi)這次事件
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


12、我們在ViewGroup2的onInterceptTouchEvent 返回true攔截此次事件并且在ViewGroup 1 的onTouchEvent返回true消費(fèi)這次事件。
紅色的箭頭代表ACTION_DOWN 事件的流向
藍(lán)色的箭頭代表ACTION_MOVE 和 ACTION_UP 事件的流向


一下子畫了好多圖,還有好幾種情況就不再畫了,相信你也看出規(guī)律了,對于在onTouchEvent消費(fèi)事件的情況:在哪個View的onTouchEvent 返回true,那么ACTION_MOVE和ACTION_UP的事件從上往下傳到這個View后就不再往下傳遞了,而直接傳給自己的onTouchEvent 并結(jié)束本次事件傳遞過程。

對于ACTION_MOVE、ACTION_UP總結(jié):ACTION_DOWN事件在哪個控件消費(fèi)了(return true), ?那么ACTION_MOVE和ACTION_UP就會從上往下(通過dispatchTouchEvent)做事件分發(fā)往下傳,就只會傳到這個控件,不會繼續(xù)往下傳,如果ACTION_DOWN事件是在dispatchTouchEvent消費(fèi),那么事件到此為止停止傳遞,如果ACTION_DOWN事件是在onTouchEvent消費(fèi)的,那么會把ACTION_MOVE或ACTION_UP事件傳給該控件的onTouchEvent處理并結(jié)束傳遞。

文/Kelin
原文鏈接:http://www.jianshu.com/p/e99b5e8bd67b#


相關(guān)閱讀:這可能是講解事件分發(fā)最好的文章了!



關(guān)于Java和Android大牛頻道

Java和Android大牛頻道是一個數(shù)萬人關(guān)注的探討Java和Android開發(fā)的公眾號,分享和原創(chuàng)最有價值的干貨文章,讓你成為這方面的大牛

我們探討android和Java開發(fā)最前沿的技術(shù):android性能優(yōu)化 ,插件化,跨平臺,動態(tài)化,加固和反破解等,也討論設(shè)計模式/軟件架構(gòu)等。由群來自BAT的工程師組成的團(tuán)隊

關(guān)注即送紅包,回復(fù):“百度” 、“阿里”、“騰訊” 有驚喜!!!關(guān)注后可用入微信群。群里都是來自百度阿里騰訊的大牛。

歡迎關(guān)注我們,一起討論技術(shù),掃描和長按下方的二維碼可快速關(guān)注我們。搜索微信公眾號:JANiubility。


公眾號:JANiubility


總結(jié)

以上是生活随笔為你收集整理的图解 Android 事件分发机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。