解决EMF里引用对象的刷新问题
假设在ecore模型里定义了两个类:产品(Product)和制造商(Manufacturer),Product通过名为manufacturer的多对一引用与Manufacturer建立关系。在应用程序里,有一些表格(TableViewer)需要在显示产品信息的同时,还要显示制造商相关信息,如制造商名称。缺省条件下,因为这些表格里每一行是一个Product实例,表格的文字更新由AdapterFactoryLabelProvider通过ProductItemProvider实现,所以在制造商名称被改变的时候产品表格无法得到更新。
当然可以直接调用viewer.refresh()方法刷新表格,但这要求具有对viewer的引用,况且我们不知道以后还会有多少个这样的viewer需要刷新。更好的解决办法是修改ProductItemProvider,让它维护一个Adapter(即EMF里的模型监听器),并把这个监听器注册到Product对应的Manufacturer实例上。监听器的注册可以在getText()方法里实现(也许有更合适的地方),别忘了在dispose()方法里要删除这个监听器。此外,要在.genmodel里把Product的Provider Type属性值从缺省的"Singleton"改为"Stateful",如下图,这样每个Product都对应一个ProductItemProvider实例,从而对应一个这样的监听器。
以下是ProductItemProvider里部分相关代码:
//Define an adapter protected Adapter manufacturerAdapter = new AdapterImpl() { public void notifyChanged(Notification notification) { //notify product viewers if manufacturer's name changed if (notification.getFeatureID(Manufacturer.class) == ProductPackage.MANUFACTURER__NAME) fireNotifyChanged(new ViewerNotification(notification, ProductItemProvider.this.getTarget(), false, true)); } }; public String getText(Object object) { Product product = (Product) object; //Add following codes to maintain the adapter Manufacturer manufacturer = product.getManufacturer(); if (manufacturer != manufacturerAdapter.getTarget()) { if (manufacturerAdapter.getTarget() != null) manufacturerAdapter.getTarget().eAdapters().remove(manufacturerAdapter); if (manufacturer != null) manufacturer.eAdapters().add(manufacturerAdapter); } String label = var.getName(); return label; } //Remove adapter when ProductItemProvider disposes public void dispose() { if (manufacturerAdapter.getTarget() != null) manufacturerAdapter.getTarget().eAdapters().remove(manufacturerAdapter); super.dispose(); }
最后,需要覆盖ProductItemProvider的notifyChanged()方法,在switch里增加如下代码:
case ProductPackage.Product__Manufacturer: fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), false, true)); return;
参考:http://dev.eclipse.org/newslists/news.eclipse.tools.emf/msg18730.html