前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jface databinding:延迟计算--ComputedValue和WritableList使用的例子

jface databinding:延迟计算--ComputedValue和WritableList使用的例子

作者头像
10km
发布2019-05-25 22:28:36
3700
发布2019-05-25 22:28:36
举报
文章被收录于专栏:10km的专栏10km的专栏

版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433700

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

代码语言:javascript
复制
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

代码语言:javascript
复制
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的确很方便,但它是有环境使用要求的。请看它的代码:

代码语言:javascript
复制
    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静态方法的代码就明白了:

代码语言:javascript
复制
    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

代码语言:javascript
复制
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方法。

例如下面的代码:

代码语言:javascript
复制
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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年12月21日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ComputedValue
  • WritableList
  • runWithDefault
  • lambda支持
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档