前言
關於Android View事件分發機制的一個小結,基於他人分析以及個人理解,方便自己記錄以及回憶,使用了一些UML圖和流程圖對部分流程進行了細化,並加入了自己的理解,期間參考了幾篇比較優秀(不同博文可能針對的Android代碼版本不同,存在些許出入,但是大致邏輯一致)的關於事件分發機制的博文,已在參考鏈接中列出。
該篇博文更適合那些對事件分發機制基本瞭解但是仍然缺少一個系統化輪廓的朋友,只是一個總結而非教程,如果完全沒有概念的話先從參考鏈接的博文開始看起!然後再回過頭來看這個總結。
如果發現有什麼問題,歡迎留言拍磚!
Activity的事件分發邏輯
- 點擊事件最先傳遞給當前的Activity,由Activity的dispatchToucnEvent來進行事件分發,具體的工作由Activity內部的Window來完成,Window會將事件傳遞給DecorView,DecorView一般就是當前界面的底層容器(即setContentView所設置的View的父容器),通過Activity.getWindow.getDecorView()可以獲得
- 如果所有的View的onTouchEvent都返回了false,那麼Activity的onTouchEvent就會被調用
- Window的唯一實現是PhoneWindow
- PhoneWindow中通過DecorView往下分發事件
- 通過((ViewGroup))getWindow().getDecorView().findViewById(android.R.id.content).getChildAt(0)可以獲得Activity所設置的View
- DecorView繼承自FrameLayout且是父View,所以最終事件會傳遞給View
ViewGroup以及View的事件分發邏輯
- ViewGroup中的onInterceptTouchEvent用來控制ViewGroup是否攔截事件向下傳遞
- ViewGroup的主要的任務是找一個Target,並且用這個target傳遞事件
- 在Down並且不攔截的時候會多出一個尋找Target的過程,在這個過程中遍歷子View,如果子View的dispatchTouch爲true(如果這裏返回false的話,那麼接下來的action就不會繼續傳遞,因爲這時的target就爲空,target爲空的話,就會觸發ViewGroup作爲一個View的dispatchTouchEvent()方法),則這個子View就是當前ViewGroup的Target。找Target是處理Down事件時候特有的,其他事件不會觸發找Target。
- 那麼上面說的View的dispatchTouchEvent一定會返回true嗎?默認情況下只要View是Clickable或者LongClickable,就一定消費事件,即返回true
- 找到Target之後如果再次調用ViewGroup的dispatchTouchEvent,就用經過一系列邏輯判斷繼續調用Target的dispatchTouchEvent
- View的onTouchEvent中,當action == MotionEvent.ACTION_UP時,就會觸發View的performClick(),所以onClick會晚於onTouch
總結和參考
有沒有發現,Android View的事件分發就是一個活生生的基於責任鏈模式實現的經典案例!
建議:可以根據自己不同的理解程度參考如下博文:
http://www.nowamagic.net/academy/detail/50160216
http://blog.csdn.net/duo2005duo/article/details/51604119
http://blog.csdn.net/guolin_blog/article/details/9153747
《Android開發藝術探索》