本文主要讲了在Oracle jdeveloper 的MAF开发中,如何用线程来实现页面组件的同步简单类型数据刷新。
一、PropertyChangeSupport
1. 首先介绍下PropertyChangeSupport
,PropertyChangeSupport
提供了2个监听器接口,一个是addPropertyChangeListener,另一个是removePropertyChangeListener,当一个实例注册了该Bean的监听器,那么当Bean中的属性值发生变化的时候,会通知所有注册到该Bean的实例。
2. 如何创建PropertyChangeSupport
?
a. 创建一个PrintLogBO.java
b. 新建一个String类别的属性,名为Single_Log;
c. 在Jedeveloper中,在代码区点击右键,选择Generate Accessors,如下图所示:
点ok后,代码更新为:
public class PrintLogBO {
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public PrintLogBO() {
super();
pass = "";
}
public void setSingle_log(String single_log) {
String oldSingle_log = this.single_log;
this.single_log = single_log;
propertyChangeSupport.firePropertyChange("single_log", oldSingle_log, single_log);
}
public String getSingle_log() {
return single_log;
}
private String single_log;
private String pass;
public void startLogThread() {
Thread thread = new Thread() {
public void run() {
for (int i = 0; i < 100; i++) {
setSingle_log("Index: " + pass);
AdfmfJavaUtilities.flushDataChangeEvent();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.start();
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
}
我们发现,增加了get, set方法,并且增加了2个监听器。
3. 新建一个测试类Test.java
public class Test implements PropertyChangeListener{
public Test() {
super();
}
public void propertyChange(PropertyChangeEvent evt) {
// TODO Implement this method
System.out.println("fire action");
}
public static void test(){
// a instance of PrintLogBO
PrintLogBO printLogBO = new PrintLogBO();
// a instance of Test
Test test = new Test();
// regist a listener
printLogBO.addPropertyChangeListener(test);
// set a new value
printLogBO.setSingle_log("a new value");
}
}
4. 创建一个data control,用test()创建一个按钮,运行设备,当点击按钮的时候,会发现Android Device Monitor 会同步打印log “fire action”
二、 flushDataChangeEvent
当我们需要同步amx页面上组件的值的时候,如果通过此方法,发现只能通过刷新页面来获取最新的值。如果通过刷新AMX页面来显示最新的数据,这样会影响效率和用户体验,因为firePropertyChange方法只是改变的缓存的值,刷新页面后,页面上的值替换成缓存的值。基于此,我们需要用到
AdfmfJavaUtilities.flushDataChangeEvent.
它可以强制将缓存的值刷新到客户页面上,但是
flushDataChangeEvent
必须在一个新的线程中存在。下面的例子将演示,在一个AMX页面上,动态显示log的方法。
1. 新建一个PrintLogBO.java,内容如下:
public class PrintLogBO {
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public PrintLogBO() {
super();
}
public void setSingle_log(String single_log) {
String oldSingle_log = this.single_log;
this.single_log = single_log;
propertyChangeSupport.firePropertyChange("single_log", oldSingle_log, single_log);
}
public String getSingle_log() {
return single_log;
}
private String single_log;
public void startLogThread() {
Thread thread = new Thread() {
public void run() {
for (int i = 0; i < 100; i++) {
setSingle_log("Index: " + i);
// import method
AdfmfJavaUtilities.flushDataChangeEvent();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.start();
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
}
新增加了一个方法,startLogThread,在方面里面AdfmfJavaUtilities.flushDataChangeEvent()方法强制将String值的改变推送到AMX页面上
2. 创建一个data control,single_log作为outputText, startLogThread作为Button
<amx:commandButton actionListener="#{bindings.startLogThread.execute}" text="startLogThread"
disabled="#{!bindings.startLogThread.enabled}" id="cb1"/>
<amx:panelLabelAndMessage label="#{bindings.single_log.hints.label}" id="plam1">
<amx:outputText value="#{bindings.single_log.inputValue}" id="ot2"/>
</amx:panelLabelAndMessage>
3. 运行Android设备,点击按钮,屏幕会动态打印log,运行截图如下:
一段时间后,截图如下:
[References]
1. http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/amxbinding.htm