Android 事件分發機制 圖解

來源:互聯網
上載者:User

標籤:作用   一個   停止   move   開發   簡單   有用   activity   isp   

    

      在Android 開發中事件分發是比較重要的,也是比較難理解的,之前看過這方面的東西,以為自己弄懂了,也就沒太注意,最近面試呢,想著肯定要問到這一塊的東西,回顧的時候發現又忘了,真是好記性不如爛筆頭啊,長期沒有用到這一塊的東西,也就拋之腦後了,今天用了半天時間,看資料有瞭解了一下,把這塊內容整理一下,省的以後在以後學習過程中,要不斷溫故一下,看的時候就不用那麼麻煩了。

      文章參考於:http://www.jianshu.com/p/e99b5e8bd67b

 

      下面就是事件分發的流程圖:

     

 

  • 仔細看的話,圖分為3層,從上往下依次是Activity、ViewGroup、View
  • 事件從左上方那個白色箭頭開始,由Activity的dispatchTouchEvent做分發
  • 箭頭的上面字代表方法傳回值,(return true、return false、return super.xxxxx(),super 的意思是調用父類實現。
  • dispatchTouchEvent和 onTouchEvent的框裡有個【true---->消費】的字,表示的意思是如果方法返回true,那麼代表事件就此消費,不會繼續往別的地方傳了,事件終止。
  • 目前所有的圖的事件是針對ACTION_DOWN的,對於ACTION_MOVE和ACTION_UP我們最後做分析。
  • 之前圖中的Activity 的dispatchTouchEvent 有誤(圖已修複),只有return super.dispatchTouchEvent(ev) 才是往下走,返回true 或者 false 事件就被消費了(終止傳遞)。

 

  

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

   

     

   

所以如果我們沒有對控制項裡面的方法進行重寫或更改傳回值,而直接用super調用父類的預設實現,那麼整個事件流嚮應該是從Activity---->ViewGroup--->View 從上往下調用dispatchTouchEvent方法,一直到葉子節點(View)的時候,再由View--->ViewGroup--->Activity從下往上調用onTouchEvent方法。
2、dispatchTouchEvent 和 onTouchEvent 一旦return true,事件就停止傳遞了(到達終點)(沒有誰能再收到這個事件)。看中只要return true事件就沒再繼續傳下去了, 對於return true我們經常說事件被消費了,消費了的意思就是事件走到這裡就是終點,不會往下傳,沒有誰能再收到這個事件了。       3、dispatchTouchEvent 和 onTouchEvent return false的時候事件都回傳給父控制項的onTouchEvent處理。   

     看深藍色的線,對於返回false的情況,事件都是傳給父控制項onTouchEvent處理。

  • 對於dispatchTouchEvent 返回 false 的含義應該是:事件停止往子View傳遞和分發同時開始往父控制項回溯(父控制項的onTouchEvent開始從下往上回傳直到某個onTouchEvent return true),事件分發機制就像遞迴,return false 的意義就是遞迴停止然後開始回溯。
  • 對於onTouchEvent return false 就比較簡單了,它就是不消費事件,並讓事件繼續往父控制項的方向從下往上流動。
  

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

 

所以如果看到方法return super.xxxxx() 那麼事件的下一個流向就是走U型下一個目標,稍微記住上面這張圖,你就能很快判斷出下一個走向是哪個控制項的哪個函數。

 


5、onInterceptTouchEvent 的作用

 

 

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

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




首先看下ViewGroup 的dispatchTouchEvent,之前說的return true是終結傳遞。return false 是回溯到父View的onTouchEvent, 然後ViewGroup怎樣通過dispatchTouchEvent方法能把事件分發到自己的onTouchEvent處理呢,return true和false 都不行,那麼只能通過Interceptor把事件攔截下來給自己的onTouchEvent,所以ViewGroup dispatchTouchEvent方法的super預設實現就是去調用onInterceptTouchEvent,記住這一點
那麼對於 View的dispatchTouchEvent return super.dispatchTouchEvent()的時候呢事件會傳到哪裡呢,很遺憾View沒有攔截器。 但是同樣的道理return true是終結。return false 是回溯會父類的onTouchEvent,怎樣把事件分發給自己的onTouchEvent 處理呢,那隻能return super.dispatchTouchEvent,View類的dispatchTouchEvent()方法預設實現就是能幫你調用View自己的onTouchEvent方法的。

說了這麼多,不知道有說清楚沒有,我這邊最後總結一下:

  • 對於 dispatchTouchEvent,onTouchEvent,return true是終結事件傳遞。return false 是回溯到父View的onTouchEvent方法。
  • ViewGroup 想把自己分發給自己的onTouchEvent,需要攔截器onInterceptTouchEvent方法return true 把事件攔截下來。
  • ViewGroup 的攔截器onInterceptTouchEvent 預設是不攔截的,所以return super.onInterceptTouchEvent()=return false;
  • View 沒有攔截器,為了讓View可以把事件分發給自己的onTouchEvent,View的dispatchTouchEvent預設實現(super)就是把事件分發給自己的onTouchEvent。

ViewGroup和View 的dispatchTouchEvent 是做事件分發,那麼這個事件可能分發出去的四個目標

註:------> 後面代表事件目標需要怎麼做。
1、 自己消費,終結傳遞。------->return true ;
2、 給自己的onTouchEvent處理-------> 調用super.dispatchTouchEvent()系統預設會去調用 onInterceptTouchEvent,在onInterceptTouchEvent return true就會去把事件分給自己的onTouchEvent處理。
3、 傳給子View------>調用super.dispatchTouchEvent()預設實現會去調用 onInterceptTouchEvent 在onInterceptTouchEvent return false,就會把事件傳給子類。
4、 不傳給子View,事件終止往下傳遞,事件開始回溯,從父View的onTouchEvent開始事件從下到上迴歸執行每個控制項的onTouchEvent------->return false;
註: 由於View沒有子View所以不需要onInterceptTouchEvent 來控制項是否把事件傳遞給子View還是攔截,所以View的事件分發調用super.dispatchTouchEvent()的時候預設把事件傳給自己的onTouchEvent處理(相當於攔截),對比ViewGroup的dispatchTouchEvent 事件分發,View的事件分發沒有上面提到的4個目標的第3點。

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

1、自己消費掉,事件終結,不再傳給誰----->return true;
2、繼續從下往上傳,不消費事件,讓父View也能收到到這個事件----->return false;View的預設實現是不消費的。所以super==false。

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

1、攔截下來,給自己的onTouchEvent處理--->return true;
2、不攔截,把事件往下傳給子View---->return false,ViewGroup預設是不攔截的,所以super==false;

 

Android 事件分發機制 圖解

相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。