本文介绍Jedeveloper MAF开发中PropertyChangeSupport 和 ProviderChangeSuppor的区别和实例分析
1. Why ProviderChangeSupport?
PropertyChangeSupport应对的是简单属性的改变,而ProviderChangeSupport应对的是Data Collections的改变
在java的api中,ProviderChangeSupport的结构为:
oracle.adfm.java.beans
Class ProviderChangeSupport
Create
-fireProviderCreate
Delete
-fireProviderDelete
Update
-fireProviderRefresh
ProviderChangeSupport有3个重要的方法,分别对应于Create, Delete, Refresh
2. demo
首先讨论不用ProviderChangeSupport的情况
a. 新建一个Test.java
public class Test{
public Test() {
super();
}
Integer id;
String dept;
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setDept(String dept) {
this.dept = dept;
}
public String getDept() {
return dept;
}
}
b. 新建一个TestDC.java
public class TestDC {
private List deptList = new ArrayList();
private Test[] tests;
private Integer test_id = new Integer(4);
private String test_dept = "sssss";
private Integer test_update_id = new Integer(5);
private String test_update_dept = "bbbbb";
public void setTests(Test[] tests) {
this.tests = tests;
deptList = new ArrayList();
for (int i = 0; i < tests.length; i++) {
deptList.add(tests[i]);
}
}
public Test[] getTests() {
return (Test[]) deptList.toArray(new Test[deptList.size()]);
}
// constructor
public TestDC() {
super();
Test test = new Test();
test.setId(new Integer(1));
test.setDept("a");
deptList.add(test);
test = new Test();
test.setId(new Integer(2));
test.setDept("b");
deptList.add(test);
test = new Test();
test.setId(new Integer(3));
test.setDept("c");
deptList.add(test);
}
// update a record
public void updateDeptList(Integer id, String dept) {
for (int i = 0; i < deptList.size(); i++) {
if (((Test) deptList.get(i)).getId().compareTo(test_id) == 0) {
// test found
Test test = (Test) deptList.get(i);
test.setId(test_update_id);
test.setDept(test_update_dept);
deptList.remove(i);
deptList.add(test);
return;
}
}
}
// add a record
public void addDeptList(Integer id, String dept) {
for(int i = 0;i<10;i++){
Test test = new Test();
test.setId(test_id);
test.setDept(test_dept);
deptList.add(test);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// remove a record
public void deleteDeptList(String id) {
for (int i = 0; i < deptList.size(); i++) {
if (((Test) deptList.get(i)).getId().compareTo(test_id) == 0) {
// test found
deptList.remove(i);
return;
}
}
}
}
c. 在AMX Page中,部分组件代码如下,其中三个按钮,分别对应添加,删除,更新三个操作,outputText用来输出dept
<amx:commandButton actionListener="#{bindings.addDeptList.execute}" text="addDeptList"
disabled="#{!bindings.addDeptList.enabled}" id="cb1"/>
<amx:commandButton actionListener="#{bindings.deleteDeptList.execute}" text="deleteDeptList"
disabled="#{!bindings.deleteDeptList.enabled}" id="cb3"/>
<amx:commandButton actionListener="#{bindings.updateDeptList.execute}" text="updateDeptList"
disabled="#{!bindings.updateDeptList.enabled}" id="cb4"/>
<amx:listView var="row" value="#{bindings.tests.collectionModel}" fetchSize="#{bindings.tests.rangeSize}"
selectedRowKeys="#{bindings.tests.collectionModel.selectedRow}"
selectionListener="#{bindings.tests.collectionModel.makeCurrent}" showMoreStrategy="autoScroll"
bufferStrategy="viewport" id="lv1">
<amx:listItem id="li1">
<amx:outputText value="#{row.dept}" id="ot2"/>
</amx:listItem>
</amx:listView>
4. 运行后发现,当点击addDeptList按钮,屏幕并没有同步刷新添加的数据,当刷新AMX page后,发现新增的数据也在page上了
d. 接着讨论使用ProviderChangeSupport的情况,Test.java不变,在TestDC.java中新增加如内容:
package mobile;
import java.util.ArrayList;
import java.util.List;
import oracle.adfmf.java.beans.ProviderChangeListener;
import oracle.adfmf.java.beans.ProviderChangeSupport;
public class TestDC {
private List deptList = new ArrayList();
<span style="color:#330099;"> protected transient ProviderChangeSupport providerChangeSupport = new ProviderChangeSupport(this);</span>
private Test[] tests;
private Integer test_id = new Integer(4);
private String test_dept = "sssss";
private Integer test_update_id = new Integer(5);
private String test_update_dept = "bbbbb";
public void setTests(Test[] tests) {
this.tests = tests;
deptList = new ArrayList();
for (int i = 0; i < tests.length; i++) {
deptList.add(tests[i]);
}
}
public Test[] getTests() {
return (Test[]) deptList.toArray(new Test[deptList.size()]);
}
<span style="color:#330099;">
public void addProviderChangeListener(ProviderChangeListener l) {
providerChangeSupport.addProviderChangeListener(l);
}
public void removeProviderChangeListener(ProviderChangeListener l) {
providerChangeSupport.removeProviderChangeListener(l);
}</span>
// constructor
public TestDC() {
super();
Test test = new Test();
test.setId(new Integer(1));
test.setDept("a");
deptList.add(test);
test = new Test();
test.setId(new Integer(2));
test.setDept("b");
deptList.add(test);
test = new Test();
test.setId(new Integer(3));
test.setDept("c");
deptList.add(test);
}
// update a record
public void updateDeptList(Integer id, String dept) {
for (int i = 0; i < deptList.size(); i++) {
if (((Test) deptList.get(i)).getId().compareTo(test) == 0) {
// test found
Test test = (Test) deptList.get(i);
test.setId(test_update_id);
test.setDept(test_update_dept);
deptList.remove(i);
deptList.add(test);
<span style="color:#330099;"> providerChangeSupport.fireProviderRefresh("tests");</span>
return;
}
}
}
// add a record
public void addDeptList(Integer id, String dept) {
Test test = new Test();
test.setId(test_id);
test.setDept(test_dept);
deptList.add(test);
<span style="color:#330099;"> providerChangeSupport.fireProviderCreate("tests", test_id, test);</span>
}
// remove a record
public void deleteDeptList(String id) {
for (int i = 0; i < deptList.size(); i++) {
if (((Test) deptList.get(i)).getId().compareTo(id) == 0) {
// test found
deptList.remove(i);
<span style="color:#330099;"> providerChangeSupport.fireProviderDelete("tests", test_id);</span>
return;
}
}
}
}
e. 重新编译部署后运行,发现当点击addDeptList按钮后,页面同步更新了新增的内容,如下图所示:
f. 总结:PropertyChangeSupport能处理简单数据类型值变化的通知,当注册到改类型的实例在值发生变化后,能收到通知;ProviderChangeSupport能处理复杂类型值变化的通知。PropertyChangeSupport和ProviderChangeSupport的好处是能将JVM层返回的数据缓存起来,减少了刷新客户端界面的频率,在一定程度上提高了效率。但是,当我们处理一个长时间的请求(如Webservice的调用,本地数据库的查找等操作),我们需要实时在客户端页面上显示处理的进程,这时,我们需要一个长时间运行的后台进程来处理,通过调用AdfmfJavaUtilities.flushDataChangeEvent
能够强制将缓存数据刷新到AMX页面上。关于如何使用后台进程,请参考下一篇文章:http://blog.csdn.net/router66/article/details/40149271
[reference]
https://www.youtube.com/watch?v=ZJePFhfVqMU
http://docs.oracle.com/cd/E35521_01/apirefs.111230/e27204/oracle/adfmf/java/beans/ProviderChangeSupport.html
http://docs.oracle.com/cd/E35521_01/apirefs.111230/e27204/oracle/adfmf/java/beans/PropertyChangeSupport.html
http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/amxbinding.htm