解决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实例,从而对应一个这样的监听器。

file

以下是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

搬家前链接:https://www.cnblogs.com/bjzhanghao/archive/2007/09/03/880854.html