主要内容:
Android App开发时,上层用的是Java语言,二者都有事件处理机制,例如,JavaGUI中的按钮点击事件,Android Button的点击事件等。
本节通过Java代码的使用,和AndroidApp的开发的对比,看一下,二者在事件处理模型中的异同。
先揭晓结论:
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事件和万事一样有其生命周期,会出生也会消亡。
事件的产生:
事件最初由事件源产生,事件源可以是GUI组件Java Bean或由生成事件能力的对象,在GUI组件情况下,事件源或者是组件的同位体(对于Abstract Window Toolkit[awt]GUI组件来说)或组件本身(对于Swing组件来说)。
事件的分发:
事件生成后放在系统事件队列内部。现在事件处于事件分发线程的控制下。事件在队列中等待处理,然后事件从事件队列中选出,送到dispatchEvent()方法,dispatchEvent()方法调用processEvent()方法并将事件的一个引用传递给processEvent()方法。
此刻,系统会查看是否有送出事件的位置,如果没有这种事件类型相应的已经注册的监听器,或者如果没有任何组件受到激活来接收事件类型,事件就被抛弃。当然上图显示的是AWTEvent类的子类的生命周期。 dispatchEvent()方法和processEvent()方法把AWTEvent作为一个参数。
但对javax.swing.event并不是AWTEvent子类,而是从EventObject直接继承过来,生成这些事件的对象也会定义fireEvent()方法,此方法将事件送到包含在对象监听器列表内的那种类型的任何监听器。
Java事件的捕获:
从上面的分析我们知道,任何事件产生到dispatchEvent()方法分发方法前,所有的事件都是存放在系统事件的队列中,而且所有的事件都由dispatchEvent()方法来分派。所以只要能重载dispatchEvent()方法就可以获取系统的所有事件,包括用户输入事件。
一般来说,系统事件队列的操作对用户来说是可以控制。它在后台自动完成所要完成的事情,使用EventQueue类可以查看甚至操纵系统事件队列。
Java提供了EventQueue类来访问甚至操纵系统事件队列。EventQueue类中封装了对系统事件队列的各种操作,除dispatchEvent()方法外,其中最关键的是提供了push()方法,允许用特定的EventQueue来代替当前的EventQueue。
只要从EventQueue类中派生一个新类,然后通过push()方法用派生类来代替当前的EventQueue类即可。这样,所有的系统事件都会转发到派生EventQueue类。
而在实际的开发中,我们并不关心事件的分派方式,也就是说,并不会重载dispatchEvent(),
因为我们的目的并不是取系统的所有事件,而是对感兴趣的事件(例如,按键,鼠标的按下与释放)进行处理,而这些事件不会凭空产生,是由事件源(例如,button,window这些GUI组件产生的)。另一个原因是,java2中已经给我们提供了事件监听这种处理方式,而且是非常安全的,并且也易于开发,
4. 如何使用事件处理模型对事件进行处理:
作为一个程序开发者,我们所要做的是创建事件监听器对象并且在被激活事件的组件中进行注册。在java中,每一个组件会产生什么样的事件,已经被定义好了。或者说,对于任何一个事件来说,哪些组件可以产生它,已经是确定的了。
为了创建事件监听器以及在被激活事件的组件中进行注册,需要了解以下四个组件概念。
事件类、事件监听器、事件处理器和适配器四个组件。
事件类:是一个名词,即用于描述事件信息;
事件监听器:是interface, 形如XXListener,而且,在java中,这些interface已经被定义好了。用来被实现,它定义了事件处理器(即事件处理的方法原型,这个方法需要被重新实现)。例如,ActionListener接口,
MouseListener接口
WindowListener接口
KeyListener接口
ItemListener接口
MouseMotionListener接口
FocusListener接口
ComponentListener接口
适配器:因为对于有的事件监听器来说(例如,MouseListener),java已经提供了实现它的类,那么我们就可以直接继承这个类,来处理事件。
Java提供了表示不同的事件的类, java.util. EventObject是事件顶层类。
需要说明的是:
1)EventObjet类提供了getSource()方法获取产生事件的源对象。
2)AWTEvent类提供了getID() 方法返回事件本性的标识符。例如,如果鼠标事件发生,能够查出是单击、拖拉、按、还是其他操作。
程序开发步骤:
所谓的创建事件监听器对象,就是创建一个类,而这个类必须实现形如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就是被激活事件的组件。
这样一来,当事件被激活时,由于已经通过addActionListener进行了事件监听器的注册,所以,就会调用到特定的事件处理方法,即actionPerformed()函数。这样,执行的结果就要看actionPerformed是具体做什么工作了。
下面,是完整的例子代码:
//Button2New.java
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");
publicvoid init() {
b1.addActionListener(new B1());
b2.addActionListener(new B2());
add(b1);
add(b2);
}
class B1 implements ActionListener { // 实现ActionListener
public void actionPerformed(ActionEvent e) {
//重写actionPerformed
getAppletContext().showStatus("Button 1");
}
}
class B2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
getAppletContext().showStatus("Button 2");
}
}
}
这是最常用的一种方式:
定义一个内部类,来实现ActionListener监听器。而在外部类中,定义一个这样的对象,去注册监听器,通过调用addActionListener方法。
需要注意的是,这个内部类对象是作为addActionListener的参数,在本类中,是直接作为匿名对象被创建的。这里,也可以不用匿名对象,而直接new 一个对象,然后,这个对象作为参数传给addActionListener。
Android事件模型(从UI角度来说):
Android事件模型与java2的事件模型处理方式一样,对事件的处理,都是采用事件监听器的方式来实现的。
Android事件监听器:
在Android框架的设计中,以事件监听器(event listener)的方式来处理UI的使用者事件。
Android框架提供了非常良好的UI事件处理机制。View用于绘制UI,每个View实例都可以向Android框架注册一个事件监听器。每个事件监听器都包含一个回调函数(callback method),
这个回调函数(callback method)主要的工作就是回应或者处理事件使用者的操作。
Event Listener: 以Click Listener为例,
View.OnClickListener是click listener,顾名思义,这是UI的动作监听器;当使用者对UI进行点击时,Android框架就会回调到View.OnClickListener的回调函数中。
View.OnClickListerner的回调函数是OnClick()。
除了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事件处理器的典型例子:
public class MyActivity extends Activity {
protected void onCreate(Bundle savedValues) {
...
// button事件监听器的设置.
Button button = (Button)findViewById(R.id.corky);
button.setOnClickListener(mCorkyListener);
}
//创建事件监听器类
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
setResult(RESULT_OK, "Corky!");
finish();
}
};
}
实际上,Android还提供了另外一种事件处理机制:Handler,相信Android App开发者都用过。