談到android事件處理,最複雜的就是對touch事件的處理,因為touch事件包括:down, move, up, cancle和多點觸控等多種情況,多點觸控的情況先不討論,因為touch有這麼多的狀態,所以touch相對來說是最難處理的,下面就來討論一下android系統是如何處理touch事件的.
1.說到事件處理,首先我們要明白,為什麼要處理事件,要了解android系統本身對事件的乙個處理過程.在實際的開發中,我們如果都用系統的基本控制項,那是不需要去處理事件的,但是如果我們用複雜的布局巢狀去做一些特殊的需求,例如:scrollview中巢狀listview,scrollview巢狀viewpager等,則會產生事件衝突,所以,由於事件衝突的存在,我們要去處理這些衝突,只有了解android的事件處理機制,才能有效的去處理事件衝突.還有就是如果我們要新開發乙個元件,則元件的所有事件都要我們自己去做處理,這種情況也需要我們去處理事件.所以:由於存在以上說到的兩種情況,我們要自己處理事件.
2.有了處理事件的動機後,接下來就要了解android系統本身是如何處理複雜的事件的.android系統為所有的事件提供了三個相關的方法,以下只以touch事件為例說明.
這三個方法分別是:
dispatchtouchevent(motionevent ev); (activity, viewgroup, view都有此方法)
onintercepttouchevent(motionevent ev); (只有viewgroup有)
ontouchevent(motionevent); (activity, viewgroup, view都有此方法)
首先要提的是,android系統對本件的處理是一層一層向下傳遞處理(樹形處理).那這棵樹是從那來的呢..就是我們的布局樹,乙個布局,無論是**編寫的布局還是xml生成的布局,android系統對它進行解析時都是將其組裝成一棵ui樹,最外層布局是整個ui樹的根.知道這個以後,再來分析事件的處理.
處理流程:當我們的手指觸控到手機螢幕時,當前處於onstart()狀態的activity最先接收到此touch事件下的acton_down,然後開始呼叫它自己dispatchtouchevent()開始進行down事件分發,如果此方法返回true,則activity不向下分發事件,則整個布局都不會收到down事件,touchevent直接到activity的ontouchevent()方法進行事件處理.如果返回false,則表示down是要被分發到下層的,此時down事件被直接分發(因為沒有過濾方法)到ui樹的根布局(即最外層的布局),根布局拿到down事件時,執行自己的dispatchtouchevent方法,返回true,則事件直接交到根布局的ontouchevent()中進行處理,false則表示還得向下分發,此時事件被傳遞到根布局的onintercepttouchevent()方法中,如果此方法返回true,表示要對此事件進行過濾,則此down事件又直接進行到根布局的ontouchevent()方法直接處理,false則,要根布局不對事件進行過濾,down事件繼續向下傳遞,直到達到目標元件後,目標元件呼叫自己的dispatchtouchevent()方法,由於是目標元件,直接分發事件到自己的ontouchevent方法中,目標元件如果處理完這個down事件後返回true,表示該事件被消費完畢,不再向上層傳遞,如果返回false,則表示沒有消費完這個down事件,down向上傳遞到自己的父元件中,父元件再進行down事件的處理.一直向上傳遞直到事件被扔到虛擬機器.down事件才算處理完成,接著呼叫move,move完了up,整個流程與down是一樣的.
這裡要強調一點的是:如果乙個元件沒有接收到down事件,那麼一定接收不到move,up事件。
通過以上的流程,我們可以明白:android系統對任何乙個事件的處理都是這樣的,分發事件,過濾事件,處理事件,下乙個事件, 分發事件,過濾事件,處理事件……一直這樣迴圈去處理所有的事件的。即:事件的分發,過濾是從根到葉的,處理則是從葉再到根的。
下面是我將上面的文字流程畫的一張處理流程圖:
從圖上看,我們可以更直觀的感受整個touch事件的處理流。
3.講了android系統是如何處理事件的整個流程,那我們實際工作中如何去處理事件呢……下面將我之前處理過的乙個例子來分析。
首先我們從根到葉去處理事件,**如下:
package com.micen.buyers.view.category;
import android.content.context;
import android.util.attributeset;
import android.util.log;
import android.view.motionevent;
import android.widget.scrollview;
import com.micen.buyers.util.util;
public class myscrollview extends scrollview
/*** 通過重寫此方法,達到對事件的處理
*/@override
public boolean dispatchtouchevent(motionevent ev)
break;
case motionevent.action_up:
break;
case motionevent.action_cancel:
break;
} return super.dispatchtouchevent(ev);
} @override
public boolean onintercepttouchevent(motionevent ev)
@override
public boolean ontouchevent(motionevent ev)
}
上述**,我們是重寫了scrollview的dispatchtouchevent()達到對事件的乙個特殊處理,如果滿足了我們的規則,則直接到ontouchevent()中處理,否則,事件被傳送到 onintercepttouchevent()中執行過濾,由於此方法中沒有過濾,則下發傳遞事件.
同樣的效果,我們從葉子開始處理事件衝突,**如下:
package com.micen.buyers.view.category;
import android.content.context;
import android.os.handler;
import android.os.message;
import android.util.attributeset;
import android.view.motionevent;
import com.micen.buyers.util.util;
public class myviewpager extends viewpager
public myviewpager(context context, attributeset attrs)
@override
public boolean dispatchtouchevent(motionevent ev)
}break;
case motionevent.action_up:
setpulltoscrollviewstatus(false);
case motionevent.action_cancel:
setpulltoscrollviewstatus(false);
break;
} return super.dispatchtouchevent(ev);
} @override
public boolean onintercepttouchevent(motionevent event)
@override
public boolean ontouchevent(motionevent event)
private void setpulltoscrollviewstatus(boolean disallowintercept)
}
總結:android事件處理流程,是每乙個搞android的人應該熟練掌握的. 事件委託處理機制
事件委託處理機制實現了在兩個沒有聯絡的物件之間建立一種事件收發機制,事件傳送方和事件監聽方互相不必知道對方的任何細節,避免物件之間的依賴,降低系統耦合性。直接上 event.h pragma once include using std map ifdef dll export define dll...
Esper事件處理機制
1.sendevent 和對應lisenter的update 方法是在同乙個執行緒裡面。所以update方法的效率會影響sendevent的執行。2.在sendevent 的時候,會呼叫matchevent的方法,這個方法會為每乙個呼叫sendevent的執行緒建立乙個dispatch的list,如...
android 訊息處理機制
首先還是推薦幾篇部落格 再來說說我的理解 訊息處理機制適用場景 比如 a 類中要控制ui介面類很多元件的屬性值,可以傳參,可以設定static,但這在有大量元件屬性值需要變化時就行不通了,這時可以運用訊息處理機制在 中通知ui介面類,在介面類中改變屬性值,並重新繪製ui.b 需要在另外的執行緒中改變...