jface databinding:延迟计算--ComputedValue和WritableList使用的例子
版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net/10km/article/details/53783629
ComputedValue
org.eclipse.core.databinding.observable.value.ComputedValue<T>
类实现IObservableValue接口,提供对象T的延迟计算特性,它提供了一个抽象方法calculate,实现这个方法就可以实现根据多个可监控对象(IObservableValue)计算更新当前对象的需求。
尼玛,好抽象,我自己都不知道在说什么,还是举个例子吧。
比如我们有一张表List<Integer>
,这张表中的元素会被修改(添加,删除,更新)。
另外一个值sum
,sum是上面这张表所有元素的和。所以如果要获取sum的值,就要对List进行求和。
下面这段代码通过实现ComputedValue<Integer>
的抽象方法calculate来完成sum的自动求和功能,println方法调用sum的getValue时会自动计算List中的所有元素的总和。
TestComputeValue.java
package testwb;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.value.ComputedValue;
import org.eclipse.jface.databinding.swt.DisplayRealm;
import org.eclipse.swt.widgets.Display;
public class TestComputeValue {
public static void main(String[] args) {
Display display = Display.getDefault();
Realm realm = DisplayRealm.getRealm(display);
// 创建一张空表
final IObservableList<Integer> addends = new WritableList<Integer>(realm);
// 向表中添加元素
addends.add(Integer.valueOf(0));
addends.add(Integer.valueOf(1));
addends.add(Integer.valueOf(2));
// 定义sum,实现calculate方法完成自动求和计算
ComputedValue<Integer> sum = new ComputedValue<Integer>() {
protected Integer calculate() {
int sum = 0;
for (Iterator<Integer> it = addends.iterator(); it.hasNext();) {
Integer addend = (Integer) it.next();
sum += addend.intValue();
}
// 返回求和结果
return sum;
}
};
// 输出sum,通过getValue获取sum时,已经自动调用calculate方法计算了List总和
System.out.println(sum.getValue()); // => 3
// 向表中动态增加一个元素,则再次输出sum的值时,已经更新
addends.add(Integer.valueOf(10));
System.out.println(sum.getValue()); // => 13
}
}
WritableList
这里要说明一下上面例子中的另一个主角WritableList,WritableList其实就是一个List,并且它实现了IObservableList接口(监控表中所有元素接口),所以可以对List中的所有元素进行监控。
我们可以将任何一个普通的java.util.List
封装成WritableList以实现对表中所有元素的监控,所以上面的示例代码也可以写成这样:
TestComputeValue2.java
package testwb;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.value.ComputedValue;
import org.eclipse.jface.databinding.swt.DisplayRealm;
import org.eclipse.swt.widgets.Display;
public class TestComputeValue2 {
public static void main(String[] args) {
Display display = Display.getDefault();
Realm realm = DisplayRealm.getRealm(display);
//构造一个List,并添加元素。
List<Integer> list = new ArrayList<Integer>();
list.add(0);
list.add(1);
list.add(2);
// 构造WritableList对象将list封装成IObservableList
final IObservableList<Integer> addends = new WritableList<Integer>(realm,list,null);
ComputedValue<Integer> sum = new ComputedValue<Integer>(realm) {
protected Integer calculate() {
int sum = 0;
for (Iterator<Integer> it = addends.iterator(); it.hasNext();) {
Integer addend = (Integer) it.next();
sum += addend.intValue();
}
return sum;
}
};
System.out.println(sum.getValue()); // => 3
addends.add(Integer.valueOf(10));
System.out.println(sum.getValue()); // => 13
System.out.println(list.size());// list中元素数目更新了,变为4,
}
}
runWithDefault
其实这个例子是我从ComputedValue源代码注释中抄来的(参见ComputedValue),只是注释中的example代码并不完整,而且还写错了(WritableList.withElementType
写成了WritableValue.withValueType
)。在修改这段代码的时候,总算算搞清楚了ComputedValue的玩儿法。
看到这时你也许会问,既然ComputedValue源码中的例子错将WritableList.withElementType
写成了WritableValue.withValueType
,你上面的代码中为什么没有用WritableList.withElementType
方法来构造WritableList对象呢?
用withElementType静态方法来构造WritableList的确很方便,但它是有环境使用要求的。请看它的代码:
public static <T> WritableList<T> withElementType(Object elementType) {
return new WritableList<T>(Realm.getDefault(), new ArrayList<T>(), elementType);
}
在调用构造函数WritableList(Realm realm, List<E> toWrap, Object elementType)
时对于第一个realm参数是用Realm.getDefault()
静态方法获取的。而默认情况下Realm.getDefault()
返回是null(why?参见Realm代码),所以使用withElementType静态方法肯定就抛出异常了。
那么什么情况下Realm.getDefault()返回不为null呢?
看下面Realm中的runWithDefault静态方法的代码就明白了:
public static void runWithDefault(Realm realm, Runnable runnable) {
Realm oldRealm = Realm.getDefault();
try {
//设置defaultRealm,只有这时defaultRealm的值才不为null
defaultRealm.set(realm);
// 执行Runnable对象
runnable.run();
} finally {
// 执行完后恢复defaultRealm
defaultRealm.set(oldRealm);
}
}
所以如果要像ComputedValue源码中的例子那样使用withElementType静态方法来构造WritableList,代码应该这样写: TestComputeValue3.java
package testwb;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.value.ComputedValue;
import org.eclipse.jface.databinding.swt.DisplayRealm;
import org.eclipse.swt.widgets.Display;
public class TestComputeValue3 {
public static void main(String[] args) {
Display display = Display.getDefault();
Realm.runWithDefault(DisplayRealm.getRealm(display), new Runnable() {
public void run() {
try {
// 调用withElementType静态方法创建WritableList对象
final IObservableList<Integer> addends = WritableList.withElementType(null);
addends.add(Integer.valueOf(0));
addends.add(Integer.valueOf(1));
addends.add(Integer.valueOf(2));
ComputedValue<Integer> sum = new ComputedValue<Integer>() {
protected Integer calculate() {
int sum = 0;
for (Iterator<Integer> it = addends.iterator(); it.hasNext();) {
Integer addend = (Integer) it.next();
sum += addend.intValue();
}
return sum;
}
};
System.out.println(sum.getValue()); // => 3
addends.add(Integer.valueOf(10));
System.out.println(sum.getValue()); // => 13
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
lambda支持
Eclipse Neon版本中ComputedValue类增加了一个新的create静态方法,来创建ComputedValue对象,create方法允许更方便的使用lamda表达来实现calculate方法。 例如下面的代码:
IObservableValue<String> lastName = // ...
IObservableValue<String> firstName = // ...
// 调用create方法通过lambda表达式作为calculate方法的实现
IObservableValue<String> formattedName = ComputedValue.create(() -> {
String lastNameValue = lastName.getValue();
String firstNameValue = firstName.getValue();
return lastNameValue + "," + firstNameValue;
});
参考: ComputedValue AJFace Data Binding - Tutorial
- docker学习(4) 一些常用操作
- Java多线程之细说线程池
- Windows8异步编程的注意事项
- Spring(一)Spring的第一滴血
- Flume(一)Flume原理解析
- 我所理解的Remoting (2) :远程对象的生命周期管理[下篇]
- struts2(六)之ognl表达式与ActionContext、ValueStack
- Windows8异步编程的注意事项
- CSS魔法堂:深入理解line-height和vertical-align
- Gradle 10分钟上手指南
- gradle项目中profile的实现
- 欧盟推出“数字经济税收制度”优化了税收制度,却影响区块链行业
- CSS魔法堂:你一定误解过的Normal flow
- ASP.NET输出JSON格式数据
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- CSP-201812-2-小明放学-Java
- Mac怎么设置docker国内镜像源来加速下载?
- 适合数据分析面试笔试入门的编程题
- 女同事问狗哥什么是线程池的阻塞队列?
- BAT某厂数据分析终面面经
- 通过常见的业务掌握SQL高级功能
- 滴滴出行数据分析师面试经验
- 如何制作推论统计分析报告
- 全局唯一 ID 服务的分布式ID生成系统
- SpringBoot 国际化实现跨地区的多语言切换
- MySQL 死锁产生原因和解决方法
- 手把手教你ShardingSphere和Mybatis拦截器实现特殊字段动态切换加密
- Swagger3.0官方starter诞生,可以扔掉那些野生starter了
- Prometheus 入门教程(一):Prometheus 快速入门
- 开发|ShiroConfig实现基础拦截