Java事件模型與Android事件模型的比較

比較結果:Android借鑑了Java2中的UI事件處理機制,但是,Android又提供了另一種事件處理器(event handler),而這個方式是否與java1.0事件模型一樣呢,有待求證。

 

Java事件模型:

我們把JDK1.0事件處理模型成爲Java1.0事件模型,而從jdk1.1後的版本事件處理模型稱爲Java 2事件處理模型。

 

1.  Java1.0事件模型:

dispatchEvent()-postEvent()-handleEvent()

 

在JDK1.0的版本採用用的事件模型,提供了基本的事件處理功能。這是一種包容模型,所有事件都封裝在單一的類Event中,所有事件對象都由單一的方法 handleEvent來處理,這些定義都在Component類中。
爲此,只有Component類的子類才能充當事件處理程序,事件處理傳遞到組件層次結構,如果目標組件不能完全處理事件,事件被傳遞到目標組件的容器。

 

在Java1.0事件處理模型中事件處理是以如下方法執行的。deliverEvent()用於決定事件的目標,目標是處理事件的組件或容器,此過程開始於GUI層的最外部而向內運作。
當按一個button時,如果檢測到是該按鈕激發的事件,該按鈕會訪問它的deliverEvent()方法,這一操作由系統完成。一旦識別目標組件,正確事件類型發往組件的postEvent()方法,該方法依次把事件送到handleEvent()方法並且等待方法的返回值。
"true"表明事件完全處理,"false"將使postEvent()方法聯繫目標容器,希望完成事件處理。

 

2. Java 2事件處理模型:

 

在Java2處理事件時,沒有采用dispatchEvent()-postEvent()-handleEvent()方式,採用了監聽器類,每個事件類都有相關聯的監聽器接口。事件從事件源到監聽者的傳遞是通過對目標監聽者對象的Java方法調用進行的。
對每個明確的事件的發生,都相應地定義一個明確的Java方法。這些方法都集中定義在事件監聽者(EventListener)接口中,這個接口要繼承 java.util.EventListener。 實現了事件監聽者接口中一些或全部方法的類就是事件監聽者。
伴隨着事件的發生,相應的狀態通常都封裝在事件狀態對象中,該對象必須繼承自java.util.EventObject。事件狀態對象作爲單參傳遞給應響應該事件的監聽者方法中。發出某種特定事件的事件源的標識是:遵從規定的設計格式爲事件監聽者定義註冊方法,並接受對指定事件監聽者接口實例的引用。

 

3. Java事件和萬事一樣有其生命週期,會出生也會消亡。下圖3.1給出了Java事件生命週期的示意圖:


 

事件最初由事件源產生,事件源可以是GUI組件Java Bean或由生成事件能力的對象,在GUI組件情況下,事件源或者是組件的同位體(對於Abstract Window Toolkit[awt]GUI組件來說)或組件本身(對於Swing組件來說)。
事件生成後放在系統事件隊列內部。現在事件處於事件分發線程的控制下。事件在隊列中等待處理,然後事件從事件隊列中選出,送到dispatchEvent()方法,dispatchEvent()方法調用processEvent()方法並將事件的一個引用傳遞給processEvent()方法。
此刻,系統會查看是否有送出事件的位置,如果沒有這種事件類型相應的已經註冊的監聽器,或者如果沒有任何組件受到激活來接收事件類型,事件就被拋棄。當然上圖顯示的是AWTEvent類的子類的生命週期。 dispatchEvent()方法和processEvent()方法把AWTEvent作爲一個參數。但對,javax.swing.event並不是AWTEvent子類,而是從EventObject直接繼承過來,生成這些事件的對象也會定義fireEvent()方法,此方法將事件送到包含在對象監聽器列表內的那種類型的任何監聽器。
3.2 Java事件捕獲
從上面的分析我們知道,任何事件產生到dispatchEvent()方法分發方法前,所有的事件都是存放在系統事件的隊列中,而且所有的事件都由dispatchEvent()方法來分派。所以只要能重載dispatchEvent()方法就可以獲取系統的所有事件,包括用戶輸入事件。一般來說,系統事件隊列的操作對用戶來說是可以控制。它在後臺自動完成所要完成的事情,使用EventQueue類可以查看甚至操縱系統事件隊列。
Java提供了EventQueue類來訪問甚至操縱系統事件隊列。EventQueue類中封裝了對系統事件隊列的各種操作,除dispatchEvent()方法外,其中最關鍵的是提供了push()方法,允許用特定的EventQueue來代替當前的EventQueue。
只要從EventQueue類中派生一個新類,然後通過push()方法用派生類來代替當前的EventQueue類即可。這樣,所有的系統事件都會轉發到派生EventQueue類。

 

而在實際的開發中,我們並不關心事件的分派方式,也就是說,並不會重載dispatchEvent(),

因爲我們的目的並不是取系統的所有事件,而是對感興趣的事件(例如,按鍵,鼠標的按下與釋放)進行處理,而這些事件不會憑空產生,是由事件源(例如,button,window這些GUI組件產生的)。另一個原因是,java2中已經給我們提供了事件監聽這種處理方式,而且是非常安全的,並且也易於開發,

 

4. 如何使用事件處理模型對事件進行處理:

作爲一個程序開發者,我們所要做的是創建事件監聽器對象並且在被激活事件的組件中進行註冊。在java中,每一個組件會產生什麼樣的事件,已經被定義好了。或者說,對於任何一個事件來說,哪些組件可以產生它,已經是確定的了。

 

(1) 爲了創建事件監聽器以及在被激活事件的組件中進行註冊,需要了解以下四個組件概念。

 

事件類、事件監聽器、事件處理器和適配器四個組件。

事件類:見圖4.1

事件監聽器:是interface, 形中XXListener,而且,在java中,這些interface已經被定義好了。用來被實現,它定義了事件處理器(即事件處理的方法原型,這個方法需要被重新實現)。例如,ActionListener接口,

MouseListener接口

WindowListener接口

KeyListener接口

ItemListener接口

MouseMotionListener接口

FocusListener接口

ComponentListener接口

 

 

適配器:因爲對於有的事件監聽器來說(例如,MouseListener

),java已經提供了實現它的類,那麼我們就可以直接繼承這個類,來處理事件。

Java提供了表示不同的事件的類, java.util. EventObject是事件頂層類,其層次結構如下:


 

                         圖4.1

 

需要說明的是:

̶               EventObjet類提供了getSource()方法獲取產生事件的源對象。

̶               AWTEvent類提供了getID() 方法返回事件本性的標識符。例如,如果鼠標事件發生,能夠查出是單擊、拖拉、按、還是其他操作。

 

(2)程序開發步驟:

所謂的創建事件監聽器對象,就是創建一個類,而這個類必須實現形如XXListener的接口(或者繼承”已經實現了XXListener的類”),當然,實現這個接口就意味着重寫XXListener的方法。例如,對於ActionListener, 只有一個actionPerformed方法:

 

class B1 implements ActionListener {                         // 實現ActionListener

public void actionPerformed(ActionEvent e) {    //重寫actionPerformed      getAppletContext().showStatus("Button 1");

}

在被激活事件的組件中註冊事件監聽器: 即調用形如addXXListener()的方法,例如:

Button b1 = new Button("Button 1"),b1.addActionListener(new B1()); //註冊事件監聽器,b1就是被激活事件的組件這樣一來,當事件被激活時,處理流程如下(根據圖3.1對照來看):由於已經通過addActionListener進行了事件監聽器的註冊,所以,就會調用到特定的事件處理方法,即actionPerformed()函數。這樣,執行的結果就要看actionPerformed是具體做什麼工作了。 完整的例子(來源於think in java 13.16.1節): //: Button2New.java// Capturing button pressesimport java.awt.*;import java.awt.event.*; // Must add thisimport java.applet.*; public class Button2New extends Applet {  Button    b1 = new Button("Button 1"),    b2 = new Button("Button 2");  public void init() {    b1.addActionListener(new B1());    b2.addActionListener(new B2());    add(b1);    add(b2);  }  class B1 implements ActionListener {    public void actionPerformed(ActionEvent e) {      getAppletContext().showStatus("Button 1");    }  }  class B2 implements ActionListener {    public void actionPerformed(ActionEvent e) {      getAppletContext().showStatus("Button 2");    }  }}  這是最常用的一種方式:定義一個內部類,來實現ActionListener監聽器。而在外部類中,定義一個這樣的對象,去註冊監聽器,通過調用addActionListener方法,需要注意的是,這個內部類對象是作爲addActionListener的參數,在本類中,是直接作爲匿名對象被創建的。這裏,也可以不用匿名對象,而直接new 一個對象,然後,這個對象作爲參數傳給addActionListener。 考慮:不用匿名對象與用匿名對象的區別? 更多的例子,請參考《think in java 13.16》,推薦編碼方法見《think in java 13.16.7推薦編碼方法》 Android事件模型(從UI角度來說): 從網上摘抄了一些相關文章(共5篇),從這幾篇文章來看,Android事件模型與java2的事件模型處理方式一樣,對事件的處理,都是採用事件監聽器的方式來實現的。

文章1:

Jollen 的 Android 教學,#15: 什麼是事件監聽器(Event Listener)?

 

學會產生基本的UI後,接著就要學習UI的事件處理(UI Events),才能讓UI與使用者「互動」。

什麼是事件監聽器(Event Listener)

UI的使用者事件處理,即View如何處理使用者的操作,是一個重要的課題。View是重要的類別,它是與使用者互動的前線;在Android框架的設計中,以事件監聽器(event listener)的方式來處理UI的使用者事件。

Android框架提供了非常良好的UI事件處理機制。先前的教學提到,View是繪製UI的類別,每個View物件都可以向Android框架註冊一個事件監聽器。每個事件監聽器都包含一個回呼函數(callback method),

這個回呼函數(callback method)主要的工作就是回應或處理使用者的操作。

Event Listener: 以Click Listener為例

以「使用者觸碰(touch)」的動作來說,當View要處理使用者觸碰的事件時,就要向Android框架註冊View.OnClickListener事件監聽器;當「touch」事件發生時,Android框架便回呼事件監聽器裡的回呼函數。

View.OnClickListener是click listener,故名思意,這是UI的「Click動作監聽器」;當使用者對View進行Click操作時(即觸控畫面上的UI元件),Android 框架便會回呼這個View.OnClickListener的回呼函數。

View.OnClickListerner的回呼函數為OnClick()。

這裡所提到的監聽器泛指event listener,主要用來「監聽」使用者的各種動作。除了View.OnClickListener外,Android框架還有以下的event listener(及其callback method):

·View.OnLongClickListener: onLongClick()

·View.OnFocusChangeListener: onFocusChange()

·View.OnKeyListener: onKey()

·View.OnTouchListener: onTouch()

·View.OnCreateContextMenuListener: onCreateContextMenu()

另外一種處理UI事件的機制為事件處理器(event handler),event handler與event listener是不一樣的二種處理機制。在自訂Android component的教學裡,再介紹這個部份。

文章2:

如果玩過數獨遊戲,就會知道該遊戲有時候非常容易,而有時候簡直令人抓狂。因此,當用戶選擇New Game按鈕時,就應該彈出一個對話框,要求用戶從3個難度級別中選擇一個。在Android中,從事件列表中選擇某個事件非常容易實現。首先,需要在res/values/strings.xml文件中再添加幾個字符串:


其次,使用數組資源在res/values/arrays.xml文件中創建難度列表:


然後,在Sudoku類中再導入幾個包:


最後,在onClick()方法的switch語句中添加處理New Game按鈕單擊事件的代碼:


其中,openNewGameDialog()方法的作用是創建一個處理難度列表的用戶界面。

 


 

 

setItems()方法有兩個參數:條目列表的資源ID和一個監聽器,用戶選擇某個條目時,該監聽器將被調用。

現在,運行該程序並按下New Game,將會出現如圖3-12中所示的對話框。


圖3-12 選擇難度級別對話框

實際上,此時我們並不打算開始一次新遊戲。因此,當用戶選擇某個難度級別時,該程序只是利用Log.d()方法輸出一條調試消息。Log.d()方法接收兩個參數:一個標記字符串和要輸出的一條消息。

文章3:

 

Widget中事件監聽器的實現

Widget中事件監聽器的實現


widget中是沒有click listener的,那麼如何實現點擊的動作呢?我們可以通過廣播的形式來替代click linstener。

我們知道widget其實就是一個BroadcastReceiver,所以在AndroidManifest.xml中,註冊一個新的action:
<receiver android:name="XXX">
        <meta-data android:name="android.appwidget.provider"
                                android:resource="@xml/XXX">
        </meta-data>
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="com.android.CLICK"></action>
        </intent-filter>
</receiver>

代碼中需要觸發點擊事件的地方發送一個廣播:

  Intent intent = new Intent("com.android.CLICK");
  PendingIntent pi = PendingIntent
                                .getBroadcast(context, 0, intent, 0);
  views.setOnClickPendingIntent(R.id.textview, pi);

在widget的onReceive() 方法中接收這個廣播:

  public void onReceive(Context context, Intent intent) {
                super.onReceive(context, intent);
                String action = intent.getAction();
                if (action.equals("com.android.CLICK")) {
                        //TODO  處理點擊事件
                }
        }

這樣就完成了widget中的一次點擊事件
 
 
 TOP
 


文章4:

Reference/android/view/View
From Android中文網
Android中文網(androidcn.net) 版權申明 : creativecommons licenses

Jump to: navigation, search

android.view

公有類

android.view.View

java.lang.Object

android.view.View Drawable.Callback KeyEvent.Callback

視圖(View)類代表了一種基本的用戶界面組成模塊。一個視圖佔據了屏幕上的一個矩形區域,並響應繪製圖形和事件處理。視圖類是窗體類(Widget)的基類,而窗體類用來生成可交互的用戶圖形接口(interactive GUI)。

視圖類的使用窗口中所有的視圖構成一個樹形結構。要想增加視圖,既可以用直接添加代碼的方法,也可以在一個或者多個XML文件中聲明新視圖構成的樹。在視圖類的子類中,有的可以用來控制,有的具有顯示文字、圖片或者其他內容的功能。

當視圖樹被創建後,以下這若干種通用操作將可以被使用: 1.設置屬性(properties):比如,可以設置TextView類的一個實例的文本內容。不同的子類可以用來設置的屬性與方法不同。注意:只有編譯時能夠檢測到的屬性纔可以在XML佈局管理(layout)文件中設置。

2.設置輸入焦點(focus):爲了響應用戶輸入,整個框架將處理移動的焦點。如果想把焦點強制指向某一個特定的視圖,必須調用requestFocus()方法。

3.設置監聽器(listener):在視圖中,允許設置監聽器來捕獲用戶感興趣的某些事件。比如說,在所有的視圖中,無論視圖是獲得焦點還是失去焦點,都可以通過設置監聽器來捕獲。可以通過調用setOnFocusChangeListener(View.OnFocusChangeListener)來註冊一個監聽器。在其他視圖子類中,提供了一些更加特殊的監聽器。比如,一個按鍵(Button)可以觸發按鍵被按下的事件。

4.設置是否可視(visibility):可以通過調用setVisibility(int)來顯示或者隱藏視圖。

取自"http://www.androidcn.net/wiki/index.php/Reference/android/view/View"

 

文章5:

監聽UI事件通知
Some UI notifications are automatically exposed and called by Android. For instance, Activity exposes overrideable methods onKeyDown and onKeyUp, and Widget exposes onFocusChanged(boolean, int). However, some important callbacks, such as button clicks, are not exposed natively, and must be registered for manually, as shown here.

 

   public class SendResult extends Activity   {   /**    * Initialization of the Screen after it is first created.  Must at least    * call setContentView() to    * describe what is to be displayed in the screen.    */   protected void onCreate(Bundle savedValues)   {       ...       // Listen for button clicks.       Button button = (Button)findViewById(R.id.corky);       button.setOnClickListener(mCorkyListener);   }   // Create an anonymous class to act as a button click listener.   private OnClickListener mCorkyListener = new OnClickListener()   {       public void onClick(View v)       {           // To send a result, simply call setResult() before your           // activity is finished.           setResult(RESULT_OK, "Corky!");           finish();       }   };

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/liranke/archive/2009/10/29/4740844.aspx

轉自 http://blog.csdn.net/liranke/archive/2009/10/29/4740844.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章