Java TreeViewer仅延迟加载图标

Java TreeViewer仅延迟加载图标,java,eclipse,eclipse-plugin,swt,eclipse-rcp,Java,Eclipse,Eclipse Plugin,Swt,Eclipse Rcp,我有一个TreeViewer,它显示项目列表。我的限制如下: 每个项都表示为磁盘上的一个XML文件 每个XML文件的文件名是图标的标签('hello.XML'->树中的'hello'项) 每个XML文件都有一个“类型”,存储在XML中,它表示每个项目的图像 当我为by TreeViewer项执行getChildren()时,我读取每个XML文件并从中生成Object[]数组。直到最近,这一点还是可以接受的,但现在已经不是了。XML文件的正常数量是10个,现在是500个 我需要提高表现。然而,

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

  • 每个项都表示为磁盘上的一个XML文件
  • 每个XML文件的文件名是图标的标签('hello.XML'->树中的'hello'项)
  • 每个XML文件都有一个“类型”,存储在XML中,它表示每个项目的图像
当我为by TreeViewer项执行getChildren()时,我读取每个XML文件并从中生成Object[]数组。直到最近,这一点还是可以接受的,但现在已经不是了。XML文件的正常数量是10个,现在是500个

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

  • 无法更改XML文件的格式(即使用数据库、序列化对象..)
  • 无法创建XML文件的其他表示形式
  • 无法更改XML文件的名称(即“hello.XML”->“hello type.XML”
从我的测试中发现,当只获取XML文件的目录列表并将其用于标签时,性能是合理的。标签名称是最重要的方面,虽然图像类型很有用,但并不需要立即显示

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

  • 初始getChilren()扫描XML文件目录,并返回带有“缺少”类型映像的标签列表。(getImage()=missingImage)
  • 然后,getChilren()启动后台作业,读取XML文件并获取类型
  • 每个对象[]都有一个cacheImage()方法,该方法加载到类型image中(因此getImage()==properIcon)。此方法由作业调用
  • 然后,作业迭代树中的每个项目,并为每个项目调用update()
  • 我已经实现了这一点,性能还有待提高。此外,因为我们有太多调用Display.getDefault().asyncExec来进行更新,GUI(虽然仍然是响应性的)将需要时间来响应用户交互(而不是实际锁定)。有什么方法可以改进这一点吗

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

    • 使用DeferredTreeContentManager-之所以不这样做是因为我希望首先快速地获得名称,图像可以按照自己的速度后续
    • 一次对所有项目执行update()/批处理项目-这会锁定GUI,比许多单独的update()更糟糕

    如果您将所有图像加载到后台作业中的ImageRegistry(可能使用XML),然后简单地从该注册表添加图像,这会有帮助吗?

    我建议以下优化策略(按顺序)

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

  • 如果1本身不够(不太可能)树形类有API来跟踪哪些项是可见的,并且可以侦听滚动事件。这里的想法是对可见的项进行图像计算的优先级排序,并在它们可见之后才调用更新项。


  • 尝试通过调用来降低后台线程的优先级

    this.setPriority(this.getPriority()-1);
    
    线程中

    asyncExec
    的500次调用不应使GUI无响应,如果它们所做的只是在
    TreeItem
    中设置一个映像。要确保对
    TreeViewer.update
    的调用便宜,请调用

    TreeViewer.setUseHashlookup(true)
    

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

    我建议在后台线程中一次加载/创建多个图像(从您所说的听起来,您至少可以在没有性能问题的情况下执行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);
        }
    });
    

    如果我不清楚,很抱歉。该类型可以是5种类型中的1种,每种类型由一个图像表示。这5种图像中的每一种都已加载到ImageRegistry中。缓慢的是决定显示哪个图像,然后再显示它。接受TreeViewer。setUseHashlookup(true),这是我错过的一个明显的技巧。其他技术(如批处理)倾向于不提高绩效。