Java事件模型与Android事件模型的比较

比较结果:Android借鉴了Java2中的UI事件处理机制,但是,Android又提供了另一种事件處理器(event handler),而这个方式是正好与java1.0事件模型一样。另外,如此熟悉的event handler,在QT中的事件处理机制中也有体现。如此看来,google的拿来主义运用的是如此淋漓尽致。

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 presses
import  java.awt.*; 
import  java.awt.event.*;  // Must add this 
import  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.OnClickListenerclick 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 handlerevent 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);

widgetonReceive() 方法中接收这个广播:

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(); 
  } 
  }; 

更多相关文章

  1. 另类方法屏蔽Android4.03的HOME按键
  2. android SDK更新方法总结
  3. android设置Activity背景色为透明的2种方法
  4. Android菜鸟的成长笔记(11)——Android中的事件处理
  5. android中设置分隔线几种方法
  6. android 使用DigestUtilsmd5加密的方法
  7. Android事件处理
  8. Android getWindow().setFlags方法与SD卡权限
  9. Android之各种事件触发方案

随机推荐

  1. 单独编译android模块
  2. 关于Android中android.content.res.Resou
  3. android(25)(android下实现多线程断点下载)
  4. Android Studio新建项目Rendering Proble
  5. Android电池管理
  6. android 蓝牙driver的启动流程
  7. Android中的compileSdkVersion,minSdkVers
  8. LinearLayout布局中layout_weight的用法
  9. android输出log信息
  10. Android 编译App报错 找不到android.supp