java之监听器详解

时间:2021-06-23 04:38:12

来自:http://my.oschina.net/lzwenme/blog/159864

监听器接口定义了一个类要成为监听器必须具备的功能。所有的监听器接口也都必须继承监听器接口基类 java.util.EventListener;EventListener本身没有定义任何方法,它只是一个标志接口,用来表明所有继承自 EventListener的接口属于监听器接口。 

监听器接口定义了监听器必须实现的方法。可以在监听器接口中定义任意多的事件处理方法,取决于应用所需,事件处理方法以事件对象作为入口参数,包含对事件进行处理的代码,方法名称任意,如processEvent或者handleEvent之类。 

监听器是监听器接口的实现者,提供监听器接口中定义的所有方法的实现代码。简单情形下,一个监听器只监听一种类型的事件,即实现一种监听器接口。复杂的监 听器可以实现多种监听器接口,监听多种类型的事件。在事件处理方法代码中,监听器可以从入口参数中获得事件对象,并通过该对象获得所需的信息,例如事件 源、事件发生时间等等。事件源是一定可以从事件对象中 获得的,因为事件基类EventObject提供了getSource()方法,除此以外,能从事件对象中获得的信息,取决于事件类的定义。 

作为事件源的类,必需满足以下条件:
事件源必须在内部维护一个已注册监听器的列表。当某监听器注册时,该监听器被添加到列表中,而监听器注销时,则从列表中删除;
事件源必须提供注册方法,以允许监听器注册为事件的接收者;
事件源必须提供注销方法,以允许监听器注销,停止对事件的接收;
事件源必须能够实例化事件类,即产生事件对象;

当事件对象被产生后,事件源必须向所有的注册监听器广播该消息。事件的广播,是通过逐个调用监听器列表中所有监听器的事件处理方法来实现的。

在Java的事件驱动模式中,事件源是最复杂的。多数情况下,程序员只需编写监听器的代码,而并不需要编写事件源代码。


//事件源定义

public class DemoSource {


public DemoSource() {


}



//触发DemoEvent事件。


public void fireEvent() {


DemoEvent event = new DemoEvent(this);


broadcast(event);


}


// 监听器列表


private List<DemoListener> listenerList = new ArrayList<DemoListener>();


// 监听器注册方法


public void addListener(DemoListener listener) {


listenerList.add(listener);


}


// 监听器注销方法


public void removeListener(DemoListener listener) {


listenerList.remove(listener);


}


// 事件广播方法


public void broadcast(DemoEvent event) {


for(DemoListener listener : listenerList)


listener.handleEvent(event);


}


}

//事件定义
public class DemoEvent extends EventObject{
public DemoEvent(DemoSource source){
super(source)
}
}

//监听器接口定义
public interface DemoListener extends EventListener{
public void eventHandle(DemoEvent e);
}

//监听器定义
public class MyListener implements DemoListener{
public void eventHandle(DemoEvent e){
...
}
}

//事件驱动
构造事件源对象,调用fireEvent方法,监听器就会执行相应的代码。



下面来自: ttp://estimote.github.io/Android-SDK/JavaDocs/


一、先看看jdk提供的event包:
public interface EventListener:所有事件侦听器接口必须扩展的标记接口。

java之监听器详解
package java.util;

/**
* A tagging interface that all event listener interfaces must extend.
*
@since JDK1.1
*/
public interface EventListener {
}
java之监听器详解

public class EventObject extends Object implements Serializable所有事件状态对象都将从其派生的根类。 所有 Event 在构造时都引用了对象 "source",在逻辑上认为该对象是最初发生有关 Event 的对象。

java之监听器详解
package java.util;

public class EventObject implements java.io.Serializable {

private static final long serialVersionUID = 5516075349620653480L;

/**
* The object on which the Event initially occurred.
*/
protected transient Object source;

/**
* Constructs a prototypical Event.
*
*
@param source The object on which the Event initially occurred.
*
@exception IllegalArgumentException if source is null.
*/
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");

this.source = source;
}

public Object getSource() {
return source;
}

}
java之监听器详解

 

监听器接口定义了一个类要成为监听器必须具备的功能。所有的监听器接口也都必须继承监听器接口基类 java.util.EventListener;EventListener本身没有定义任何方法,它只是一个标志接口,用来表明所有继承自 EventListener的接口属于监听器接口。 
监听器接口定义了监听器必须实现的方法。事件处理方法以事件对象作为入口参数,包含对事件进行处理的代码,方法名称任意,如processEvent或者handleEvent之类。 

监听器是监听器接口的实现者,提供监听器接口中定义的所有方法的实现代码。简单情形下,一个监听器只监听一种类型的事件,即实现一种监听器接口。复杂的监 听器可以实现多种监听器接口,监听多种类型的事件。在事件处理方法代码中,监听器可以从入口参数中获得事件对象,并通过该对象获得所需的信息,例如事件 源、事件发生时间等等。事件源是一定可以从事件对象中 获得的,因为事件基类EventObject提供了getSource()方法,除此以外,能从事件对象中获得的信息,取决于事件类的定义。 

作为事件源的类,必需满足以下条件:
事件源必须在内部维护一个已注册监听器的列表。当某监听器注册时,该监听器被添加到列表中,而监听器注销时,则从列表中删除;
事件源必须提供注册方法,以允许监听器注册为事件的接收者;
事件源必须提供注销方法,以允许监听器注销,停止对事件的接收;
事件源必须能够实例化事件类,即产生事件对象;

当事件对象被产生后,事件源必须向所有的注册监听器广播该消息。事件的广播,是通过逐个调用监听器列表中所有监听器的事件处理方法来实现的。

在Java的事件驱动模式中,事件源是最复杂的。多数情况下,程序员只需编写监听器的代码,而并不需要编写事件源代码。

 

二、代码实现

1、定义自己业务相关的事件:

java之监听器详解
package test.listener;

import java.util.EventObject;

public class DoorEvent extends EventObject {
private String doorState = "open";

public DoorEvent(Object source) {
super(source);
}

public DoorEvent(Object source, String state) {
super(source);
doorState
= state;
}

public String getDoorState() {
return doorState;
}

public void setDoorState(String doorState) {
this.doorState = doorState;
}
}
java之监听器详解

 

2、相应的事件监听器接口,和实现类

java之监听器详解
package test.listener;

import java.util.EventListener;

public interface DoorListener extends EventListener{
public void doorOpen(DoorEvent event);
}
java之监听器详解

 

实现类

java之监听器详解
package test.listener;

public class DoorListenerImpl implements DoorListener {

@Override
public void doorOpen(DoorEvent event) {
if (event.getDoorState()!=null && event.getDoorState().equals("open")) {
System.out.println(
"door is open");
}
else {
System.out.println(
"door is closed");
}
}
}
java之监听器详解

 

3、事件源,必须要有注册、注销监听器的方法

123456789101112131415161718192021222324252627282930313233343536 package test.listener; import java.util.HashSet;import java.util.Set; public class DoorManager {    private Set<DoorListener> listeners;     public void addDoorListener(DoorListener listener) {        if (null == listeners) listeners = new HashSet<DoorListener>();        listeners.add(listener);    }         public void removeDoorListener(DoorListener listener) {        if (listeners == null)return;        listeners.remove(listener);    }         protected void fireWorkspaceOpened() {        if (listeners == null)return;        DoorEvent event = new DoorEvent(this,"open");        notifyListener(event);    }         protected void fireWorkspaceClosed() {        if (listeners == null)return;        DoorEvent event = new DoorEvent(this,"closed");        notifyListener(event);    }         private void notifyListener(DoorEvent event) {        for (DoorListener listener : listeners) {            listener.doorOpen(event);        }    }}

4、main

java之监听器详解
package test.listener;

public class App {

public static void main(String[] args) {
DoorManager manager
= new DoorManager();
manager.addDoorListener(
new DoorListenerImpl());
manager.addDoorListener(
new DoorListener() {
@Override
public void doorOpen(DoorEvent event) {
System.out.println(
"break the door");
}
});
//
manager.fireWorkspaceOpened();
//
manager.fireWorkspaceClosed();
}
}
java之监听器详解

 

 

 Reference

java事件处理机制(自定义事件)【转】

Java 中 Listener监听器作用和过滤器的作用,以及区别

http://my.oschina.net/lzwenme/blog/159864