1. 背景
在ABAP中,我们可以通过SET HANDLER ... FOR ...
的方式来监听某一个事件(例如ALV中的button click事件),当事件触发后,相应的hander程序会被触发。
而在有些场景下,我们可能会遇到这样的需求,也即在某些条件下,需要取消对于某事件的监听,这应该如何实现呢?
2. 解决方案
这个场景的解决方案,需要使用到ACTIVATION
关键字。其完整的语法如下:
SET HANDLER handler1 handler2 … FOR { oref |{ALL INSTANCES} }
[ACTIVATION act].
可以在ACTIVATION
关键字后,指定单字符的文本类字段,来控制handler的行为。
-
如果act的值为
'X'
(默认值),则注册事件处理程序。 -
如果act的值为空
' '
,则取消对事件处理程序的注册。
注意:
- 不能通过大规模取消注册(SET HANDLER … FOR ALL INSTANCES ACTIVATION abap_false)来取消单一注册(SET HANDLER … FOR oref ACTIVATION abap_true )。
- 反之,在大规模登记之后( SET HANDLER … FOR ALL INSTANCES ACTIVATION abap_true),个别的对象也不能被排除在登记之外(SET HANDLER … FOR oref ACTIVATION abap_false )。
另外,只要没有使用ACTIVATION abap_false
的方式取消事件处理程序或删除注册的引发实例oref
,ABAP的垃圾收集器(Garbage Collector)就不会删除相关对象,因为它仍然被运行时框架使用。因此,从性能的角度考量,在事件响应后,应考虑是否需要取消对于事件的继续监听。
3. 示例
下面的示例代码展示了如何取消事件监听。
首先,为类LCL_TRIGGER中事件EVENT的所有实例,都注册事件处理程序,因而,所有用NEW创建的实例的事件都会被lo_hander处理,直到注册停止。
REPORT zevent_test.
CLASS lcl_trigger DEFINITION.
PUBLIC SECTION.
EVENTS event
EXPORTING VALUE(msg) TYPE string DEFAULT `nop`.
METHODS raise_event
IMPORTING iv_msg TYPE string.
ENDCLASS.
CLASS lcl_trigger IMPLEMENTATION.
METHOD raise_event.
RAISE EVENT event EXPORTING msg = iv_msg.
ENDMETHOD.
ENDCLASS.
CLASS lcl_hander DEFINITION.
PUBLIC SECTION.
METHODS handle_event FOR EVENT event OF lcl_trigger
IMPORTING msg.
ENDCLASS.
CLASS lcl_hander IMPLEMENTATION.
METHOD handle_event.
write / msg .
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
" 1) register event hander to monitor EVENT
FINAL(lo_handler) = NEW lcl_hander( ).
SET HANDLER lo_handler->handle_event FOR ALL INSTANCES ACTIVATION abap_true.
" 2) simulate event is triggered
NEW lcl_trigger( )->raise_event( `Ping 1` ).
NEW lcl_trigger( )->raise_event( `Ping 2` ).
NEW lcl_trigger( )->raise_event( `Ping 3` ).
" 3) de-register the monitor of EVENT
SET HANDLER lo_handler->handle_event FOR ALL INSTANCES ACTIVATION abap_false.
" 4) see what will happen after de-resigering
NEW lcl_trigger( )->raise_event( `Ping 4` ).
NEW lcl_trigger( )->raise_event( `Ping 5` ).
NEW lcl_trigger( )->raise_event( `Ping 6` ).
程序的运行结果如下:
在关闭事件监听后,新触发的事假将不会再被响应。
4. 小结
本文简介了ABAP中事件EVENT的用法,并介绍了如何取消对于某一事件的监听。