TreeViewer只延迟加载图标

时间:2011-03-01 12:23:05

标签: java eclipse eclipse-plugin swt eclipse-rcp

我有一个TreeViewer,它显示一个项目列表。我的约束如下:

  • 每个项目都表示为磁盘上的XML文件。
  • 每个XML文件的文件名是图标的标签('hello.xml' - >项目'hello'在树中)
  • 每个XML文件都有一个“类型”,存储在XML中,这代表每个项目的图像

当我通过TreeViewer项目执行getChildren()时,我读入每个XML文件并从那里生成Object []数组。直到最近,这已经被接受,但现在已经不复存在了。正常数量的XML文件是10,现在是500。

我需要提高性能。但是,由于各种原因,例如兼容性,以下选项是不可能的

  • 无法更改XML文件的格式(即使用数据库,序列化对象..)
  • 无法创建XML文件的其他表示
  • 无法更改XML文件的名称(即'hello.xml' - >'hello-type.xml'

在我的测试中,只需获取XML文件的目录列表并将其用于标签即可获得合理的性能。标签名称是最重要的方面,虽然图像类型很有用,但不需要立即使用。

这些要求和约束使我得到以下解决方案:

  1. 初始化getChilren()扫描XML文件的目录,并返回带有“缺失”类型图像的标签列表。 (getImage()= missingImage)
  2. getChilren()然后启动一个后台作业,该作业读入XML文件并获得该类型。
  3. 每个Object []都有一个cacheImage()方法,它加载在类型图像中(所以现在getImage()== properIcon)。这是由约翰打来的。
  4. Job然后遍历树中的每个项目并为每个项目调用update()
  5. 我已经实现了这一点,性能还有待提高。另外,因为我们有很多调用Display.getDefault()。asyncExec来进行更新,所以GUI(虽然仍然是响应式的)需要时间来响应用户交互(而不是实际锁定)。有什么方法可以改善这个吗?

    以下内容已经过考虑/尝试过:

    • 使用DeferredTreeContentManager - 没有这样做,因为我希望首先快速获取名称,后面的图像可以按照自己的节奏进行跟踪
    • 一次对所有项目执行update()/批量处理项目 - 这会锁定GUI,比许多单独的update()s更糟糕

4 个答案:

答案 0 :(得分:1)

尝试通过调用

降低后台线程的优先级
this.setPriority(this.getPriority()-1);

Thread

asyncExec的500次调用不应该使GUI无响应,如果他们没有在TreeItem中设置图像。为确保您拨打TreeViewer.update的电话便宜,请致电

TreeViewer.setUseHashlookup(true)

可以有效地将元素映射到TreeItems。

答案 1 :(得分:0)

如果您将所有图像加载到后台作业中的ImageRegistry(可能使用XML),然后只是添加此注册表中的图像,那会不会有帮助?

答案 2 :(得分:0)

我会推荐以下优化策略(按顺序)......

  1. 批量更新通话。也就是说,有一个列表,您可以在其中存放已计算图像的内容对象。当列表大小达到某个阈值(或者用完对象)时,启动列表中当前所有对象的更新。确保首先复制列表的内容并清除列表,以便缓存线程可以继续累积。使用阈值参数,您可能会通过减少asyncExec调用次数来获得所需的性能。

  2. 如果#1本身不够(不太可能),您可能还需要考虑围绕可视区域进行优化。树类有api跟踪哪些项目是可见的,你可以听取滚动事件。这里的想法是优先考虑可见项目的图像计算,并在项目变得可见之后调用项目的更新。

答案 3 :(得分:0)

我建议在后台线程中一次加载/创建多个图像(从你所说的听起来你可以做到至少10次性能问题)。所以你的线程看起来像:

// Load/Create some number of images...

Display.asyncExcec(new Runnable() {
    public void run() {
        getTreeViewer().setRedraw(false);
        // Loop and call update on each node you loaded the image for
        getTreeViewer().setRedraw(true);
    }
});