jface_使用JFace Viewer延迟获取模型元素

jface

Eclipse JFace Viewers显示的模型元素有时需要花费大量时间来加载。 因此, 工作台提供了IDeferredWorkbenchAdapter类型以在后台获取此类模型元素。 不幸的是,似乎仅通过DeferredTreeContentManager派生的AbstractTreeViewer支持此机制。

因此,我开发了自己的通用DeferredContentManager …它可以为允许添加和删除模型元素的所有StructuredViewer类型进行后台加载。 在这篇文章中,我解释了它是如何工作的以及如何使用。



在需要(重新)使用TableViewer进行后台获取的情况下,我只发现了一个与此主题相关的旧的,尚未解决的平台错误 。 但是我怀疑问题所提议的为表查看器实现额外内容管理器的解决方案是否会非常明智。 因此,我决定尝试一个基于可用的树特定实现的概念的自制通用解决方案。

使用JFace Viewer延迟获取内容

在JFace Viewers中处理长加载模型元素的基本原理很简单。 与其直接在IContentProvider#getElements(Object)获取内容, IContentProvider#getElements(Object)数据检索委托给在后台作业中执行该操作的特定适配器。

此外,委托的getElements(Object)实现返回一个placeholder 。 只要发生数据加载,查看器就会显示出来。 同时,收集的数据将转发到更新作业 。 后者将元素附加到结构化查看器。 由于仅允许通过UI线程执行的代码进行SWT小部件访问,因此更新作业是UIJob

最后,在完成后台获取后,清理作业将删除占位符。

不应将延迟获取内容与使用SWT.VIRTUAL标志的元素的延迟加载相混淆。 尽管两种方法之间存在相似之处,但虚拟表和树通常可用于按需加载大型数据集。

延迟加载对于大小合理的数据集很有帮助,但是,数据集的检索可能很耗时,因此会阻塞UI线程。 例如,考虑获取远程数据。 万一您想知道,这两种方法当然是互斥的 ……

IDeferredWorkbenchAdapter

从开发人员的角度来看, IDeferredWorkbenchAdapter是必经之路。 它是IWorkbenchAdapter的扩展,通常负责“为工作台元素提供视觉表示和层次结构,使它们可以在UI中显示,而不必知道元素的具体类型”(如其javadoc所述)

该扩展声明了其他方法来支持延迟获取给定数据元素的子代,并且可以由适配器工厂进行注册。 考虑一个简单的pojo作为模型元素,例如:

public class ModelElement {
  [...]
}

为了从域类中抽象视觉呈现和后台加载,请提供适当的适配器实现…

public class ModelElementAdapter
  implements IDeferredWorkbenchAdapter
{
  [...]
}

…并使用适配器工厂将这两种类型映射在一起:

public class ModelElementAdapterFactory
  implements IAdapterFactory
{

  @Override
  public Object getAdapter( Object adaptableObject, Class adapterType ) {
    return new ModelElementAdapter();
  }

  @Override
  public Class[] getAdapterList() {
    return new Class[] { ModelElement.class };
  }
}

有关使用IAdaptableIWorkbenchAdapterIAdaptableFactory更多信息,您可以看看如何使用IAdaptable和IAdapterFactory? 。 遗憾的是,默认工作台内容和标签提供程序希望模型元素实现IAdaptable 。 但是,可以使用自定义提供程序来规避此问题。

以下测试草图验证了元素适应是否按预期进行:

@Test
public void testAdapterRegistration() {
  IAdapterManager manager = Platform.getAdapterManager();
  ModelElementAdapterFactory factory = new ModelElementAdapterFactory();

  manager.registerAdapters( factory, ModelElement.class );
  Object actual = manager.getAdapter( new ModelElement(), ModelElement.class );

  assertThat( actual )
    .isInstanceOf( ModelElementAdapter.class );
}

现在该实现ModelElementAdapter的数据检索功能了。 这是通过fetchDeferredChildren方法完成的:

@Override
public void fetchDeferredChildren(
  Object parent, IElementCollector collector, IProgressMonitor monitor )
{
  collector.add( loadData( parent ), monitor );
}

private Object[] loadData( Object parent ) {
  return [...]
}

费时的数据加载显然由loadData()方法处理。 将数据元素添加到IElementCollector会触发上述更新作业。 如您所见,可以通过几个步骤来划分数据获取,并且可以通过给定的IProgressMonitor报告进度。

DeferredContentManager

最后要做的是将本文中描述的机制与用于描述模型元素的查看器实例连接起来。 为此, DeferredContentManager可以调整任意查看器并将元素检索委托给相应的IDeferredWorkbenchAdapter实现。

class ModelElementContentProvider
  implements IStructuredContentProvider
{

  DeferredContentManager manager;

  @Override
  public void inputChanged(
    Viewer viewer, Object oldInput, Object newInput )
  {
    TableViewerAdapter adapter 
      = new TableViewerAdapter( ( TableViewer )viewer );
    manager = new DeferredContentManager( adapter );
  }
  
  @Override
  public Object[] getElements( Object inputElement )  {
    return manager.getChildren( inputElement );
  }

  [...]
}

自定义IStructuredContentProvider用于在其inputChanged方法中调整查看器。 getElements的实现将委托给内容管理器,后者再使用DeferredContentManager#getChildren将元素加载委托给模型元素适配器。

进行提取时,将返回一个占位符元素,以在查看器中显示“ Pending…”标签。 这是左侧标题图像中所示的情况。 在右侧,检索已完成,并且占位符已删除。

StructuredViewerAdapter

查看示例,可以清楚地了解DeferredContentManager如何支持不同的查看器类型。 内容管理器使用适当的派生StructuredViewerAdapter来修改查看器。 目前,只有用于抽象树形和表形查看器的默认适配器可用。

但是,直接为其他结构化查看器类型编写适配器是很容易的。 以下代码段显示了例如ListViewer的实现:

public class ListViewerAdapter
  extends StructuredViewerAdapter
{

  public ListViewerAdapter( AbstractListViewer listViewer ) {
    super( listViewer );
  }

  @Override
  public void remove( Object element ) {
    viewer.remove( element );
  }

  @Override
  public void addElements( Object parent, Object[] children ) {
    viewer.add( children );
  }
}

在示例中,使用此选项并将表查看器替换为列表查看器将导致以下结果:

列表查看器适配器

凉! 是不是

结论

这篇文章介绍了DeferredContentManager并展示了它如何启用使用不同的JFace Viewer进行的模型元素的后台加载。 并且,在上面引人注目的用法解释之后,如果您可能想知道从哪里获得它,那么您将在Xiliary P2存储库中找到它。 内容管理器是com.codeaffine.eclipse.ui功能的一部分:

如果您想查看代码或提出问题,也可以查看Xiliary GitHub项目:

翻译自: https://www.javacodegeeks.com/2014/12/deferred-fetching-of-model-elements-with-jface-viewers.html

jface

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值