1. 程式人生 > >Android 事件傳遞總結

Android 事件傳遞總結

Android 事件傳遞總結

首先 吐槽下17年的北京市場,簡直無法生存了,為了18年不被淘汰,只能不停的催眠自己,我愛學習,我愛鑽研,我更愛擼程式碼:


View事件分發過程詳解

首先單獨給一個View新增一個點選事件一般我們使用

button.setOnClickListener(new OnClickListener() {  
    @Override  
    public
void onClick(View v) { Log.d("TAG", "onClick execute"); } });

或者還可以使用setOnTouchListener方法

    button.setOnTouchListener(new OnTouchListener() {  
        @Override  
        public boolean onTouch(View v, MotionEvent event) {  
            Log.d("TAG", "onTouch execute, action "
+ event.getAction()); return false; } });

現在,給一個控制元件,添加了兩次監聽事件。
onTouch是優先於onClick執行的,並且onTouch執行了兩次,一次是ACTION_DOWN,一次是ACTION_UP(你還可能會有多次ACTION_MOVE的執行,如果你手抖了一下)。因此事件傳遞的順序是先經過onTouch,再傳遞到onClick。
並且 onTouch方法是有返回資料的。現在我預設返回的是false,如果我把此方法返回的資料為 true, 那麼onlick方法並不會執行。

只要你觸控到了任何一個控制元件,就一定會呼叫該控制元件的dispatchTouchEvent方法。那當我們去點選按鈕的時候,就會去呼叫View類裡的dispatchTouchEvent方法
    public boolean dispatchTouchEvent(MotionEvent event) {  
        if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
                mOnTouchListener.onTouch(this, event)) {  
            return true;  
        }  
        return onTouchEvent(event);  
    }  

原始碼中,dispatchTouchEvent 會走一個判斷,

判斷為true的話,dispatchTouchEvent方法會返回 true,
如果判斷走flase的話,會執行 onTouchEvent(event)方法

一共是三個判斷,我們一個一個分析、
第一個判斷:mOnTouchListener != null

    public void setOnTouchListener(OnTouchListener l) {  
        mOnTouchListener = l;  
    }  

看到原始碼,在我們給一個view新增點選事件的時候mOnTouchListener就被賦值了,此判斷為true

第二個判斷:(mViewFlags & ENABLED_MASK) == ENABLED
這個是 判斷當前點選的控制元件是否是enabled ,因為所有的控制元件預設為enabled(是否可點選),所以這個恆定為true;

第三個判斷: mOnTouchListener.onTouch(this, event)
其實就是去回撥控制元件註冊touch事件時的onTouch方法。也就是說如果我們在onTouch方法裡返回true,就會讓這三個條件全部成立,從而整個方法直接返回true。如果我們在onTouch方法裡返回false,就會再去執行onTouchEvent(event)方法。

結論:
首先在dispatchTouchEvent中最先執行的就是onTouch方法,因此onTouch肯定是要優先於onClick執行的,而如果在onTouch方法裡返回了true,就會讓dispatchTouchEvent方法直接返回true,不會再繼續往下執行。而列印結果也證實瞭如果onTouch返回true,onClick就不會再執行了。

所以我們可以判斷出,onClick的執行肯定在onTouchEvent(event)方法中

寫到這裡,一個View的事件傳遞流程,應該很清楚了。

面試:
1. onTouch和onTouchEvent有什麼區別?

從原始碼中可以看出,這兩個方法都是在View的dispatchTouchEvent中呼叫的,onTouch優先於onTouchEvent執行。如果在onTouch方法中通過返回true將事件消費掉,onTouchEvent將不會再執行。

ViewGroup事件分發過程詳解

當你點選了某個控制元件,首先會去呼叫該控制元件所在佈局的dispatchTouchEvent方法,然後在佈局的dispatchTouchEvent方法中找到被點選的相應控制元件,再去呼叫該控制元件的dispatchTouchEvent方法。
這是整個事件傳遞的過程

ViewGroup事件分發過程詳解