2012年7月24日星期二

ADF_172:如何使用ActiveImage组件?

运行环境:JDeveloper 11.1.2.2.0 + Oracle Database 10g Express Edition 10.2.0.1。

我们常用的组件是Image,它是用来显示图片的。那么,ActiveImage比Image特殊在哪里呢?
当内容发生改变时,ActiveImage组件可以帮助我们从后台“动态刷新”内容,用户无需做任何操作。
同样的功能如果使用Image组件来实现,就需要使用PPR的功能。

ActiveImage适用于一些滚动的新闻图片,比如本实验就是每隔2秒钟自动切换不同的图片。



重点步骤说明:

1. ActiveImage组件页面代码
<af:activeImage id="ai1" source="#{imageBean.path}"/>

2. 在adfc-config.xml中注册Managed Bean: ImageBean

<?xml version="1.0" encoding="UTF-8" ?>
<adfc-config xmlns="http://xmlns.oracle.com/adf/controller" version="1.2">
<managed-bean id="__1">
<managed-bean-name>imageBean</managed-bean-name>
<managed-bean-class>view.ImageBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</adfc-config>


3. 完整的Managed Bean代码

package view;

import java.util.Collection;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;

import oracle.adf.view.rich.activedata.ActiveModelContext;
import oracle.adf.view.rich.activedata.BaseActiveDataModel;
import oracle.adf.view.rich.event.ActiveDataEntry;
import oracle.adf.view.rich.event.ActiveDataUpdateEvent;
import oracle.adf.view.rich.activedata.ActiveDataEventUtil;
//import oracle.adfinternal.view.faces.activedata.ActiveDataEventUtil;


public class ImageBean extends BaseActiveDataModel {
public ImageBean() {
ActiveModelContext context = ActiveModelContext.getActiveModelContext();
Object[] keyPath = new String[0];
context.addActiveModelInfo(this, keyPath, "path");

timer.schedule(new UpdateTask(), 2000, 2000);
}

public String getPath() {
return image1;
}

// not needed as we do not need to connect to a (real) active data source...

protected void startActiveData(Collection<Object> rowKeys, int startChangeCount) {
}

// not needed as we do not need to disconnect from a (real) active data source...

protected void stopActiveData(Collection<Object> rowKeys) {
}

public int getCurrentChangeCount() {
return counter.get();
}

protected class UpdateTask extends TimerTask {
public void run() {
counter.incrementAndGet();

ActiveDataUpdateEvent event =
ActiveDataEventUtil.buildActiveDataUpdateEvent(ActiveDataEntry.ChangeType.UPDATE, counter.get(),
new String[0], null, new String[] { "path" },
new Object[] { (counter.get() % 2) == 0 ? image1 :
image2 });
fireActiveDataUpdate(event);
}
}

private static final String image1 = "/images/free-climber-yosemite.jpg";
private static final String image2 = "/images/rutherford-yosemite-falls.jpg";
private static final Timer timer = new Timer();
private final AtomicInteger counter = new AtomicInteger(0);
}

说明:
(1)ImageBean必须实现ActiveDataModel接口,这里是继承BaseActiveDataModel,后者实现了ActiveDataModel接口。
(2)使用ActiveModelContext注册该ActiveDataModel(即ImageBean),并把keyPath与"path"属性关联起来,这样当"path"属性发生变化时,Model层可以监听到,并通知视图层,视图层将会随之改变。
(3)使用Timer来定时启动任务UpdateTask,即执行UpdateTask类的run方法。
其中第1个参数2000表示第一次执行时延迟2秒钟, 第2个参数2000表示每2秒钟执行一次。
(4)UpdateTask类是一个多线程任务:增加计数器值,并且“引爆”数据改变事件。
(5)使用ActiveDataEventUtil创建事件,更新Model。
其中参数type表示改变事件的类型,可以设置为UPDATE, INSERT, DELETE, REFRESH,等等;
参数changeCount用来保证读取一致性;
参数key表示当前记录的key,适用于Model是CollectionModel类型的情况;
参数insertKey表示插入的位置,适用于Model是CollectionModel类型的情况;
参数names表示已改变的属性名称;
参数values表示已改变的属性值。

Project 下载:ADF_ActiveImage.7z

没有评论: