Part的构造函数被调用两次

时间:2014-05-15 23:56:52

标签: java eclipse-rcp e4

短篇小说:

我有一个类被用作e4xmi的一部分。该类有一个构造函数,用于初始化列表,以及从DS(OSGi上的声明性服务)绑定的方法。调用绑定方法时,此列表应添加或删除项目。

第一次调用构造函数(由e4自动调用,因为它是应用程序模型中的一部分),列表被初始化。好吧,这就是应该如何工作的。

之后,将一个项添加到列表中(因为框架会自动调用DS绑定方法)。但是,Part的构造函数再次被调用,初始化并清除我有一个项目的列表。

我不知道为什么框架会两次调用构造函数。我做错了什么?

长篇故事:

我想要实现的目标:

我为研究目的创建了一个简单的e4 RCP应用程序,它有一个能够在运行时加载大量小部件(时钟,天气预报,信息源等)的视图。

我认为我应该做些什么来实现这一目标:

为了实现这一点,我计划使用实现相同服务的捆绑包(即IWidget)和查找该服务的视图,并将其添加到布局中。

我目前拥有的内容:

目前我有4个捆绑包:

  • Widget包,它只有一个带有getName()方法的IWidget接口;
  • ClockWidget包,IWidget的实现;
  • MainViewPart,一个代表主视图的Part。它具有在OSGi容器中安装小部件时添加/删除小部件的方法。我是通过DS(声明性服务);
  • 来做到这一点的
  • 应用程序,一个包含e4xmi文件的项目,其中一个部件引用了MainViewPart。

这里可以找到一个简单的类图来简化说明: enter image description here

我的问题是什么:

当我运行应用程序时,MainViewPart构造函数被调用两次,正如您在输出中看到的那样:

*1. MainViewPart - Constructor
2. ClockWidget - Constructor
3. MainViewPart - Adding widget ClockWidget
*4. MainViewPart - Constructor
5. MainViewPart - @PostConstruct
6. MainViewPart - Removing widget ClockWidget

请注意,在第1行和第4行中调用了MainViewPart构造函数。 我没有看到有人在网上抱怨这个,所以我可能在这里做错了。这种奇怪的行为对我来说是一个可怕的限制。实际上我甚至不知道这是否是一个很好的方法来做我想要实现的目标。

任何帮助都将不胜感激。

来源:

ClockWidget.java:

package br.com.fernandopaz.rcp.test.widget.clock;

import br.com.fernandopaz.rcp.test.widget.IWidget;

public class ClockWidget implements IWidget {

    public ClockWidget() {
        System.out.println("ClockWidget - Constructor");
    }

    @Override
    public String getName() {
        return "ClockWidget";
    }
}

MainViewPart.java:

package br.com.fernandopaz.rcp.test.part.mainview;

import javax.annotation.PostConstruct;
import org.eclipse.swt.widgets.Composite;
import br.com.fernandopaz.rcp.test.widget.IWidget;

public class MainViewPart {

    public MainViewPart() {
        System.out.println("MainViewPart - Constructor");
    }

    @PostConstruct
    public void postConstruct(Composite parent) {
        System.out.println("MainViewPart - @PostConstruct");
    }

    public void addWidget(IWidget widget) {
        System.out.println("MainViewPart - Adding widget " + widget.getName());
    }

    public void removeWidget(IWidget widget) {
        System.out.println("MainViewPart - Removing widget " + widget.getName());
    }
}

Application.e4xmi:

<?xml version="1.0" encoding="UTF-8"?>
<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmi:id="_T7vUMNx5EeOS5eqwaRWLag" elementId="org.eclipse.e4.ide.application" bindingContexts="_T7vUOdx5EeOS5eqwaRWLag">
  <children xsi:type="basic:TrimmedWindow" xmi:id="_T7vUMdx5EeOS5eqwaRWLag" label="br.com.fernandopaz.rcp.test" width="500" height="400">
    <children xsi:type="basic:PartSashContainer" xmi:id="_t7ieENx5EeOS5eqwaRWLag" elementId="br.com.fernandopaz.rcp.test.partsashcontainer.0">
      <children xsi:type="basic:Part" xmi:id="_uRJhsNx5EeOS5eqwaRWLag" elementId="br.com.fernandopaz.rcp.test.part.0" contributionURI="bundleclass://br.com.fernandopaz.rcp.test.part.mainview/br.com.fernandopaz.rcp.test.part.mainview.MainViewPart"/>
    </children>
  </children>
  <rootContext xmi:id="_T7vUOdx5EeOS5eqwaRWLag" elementId="org.eclipse.ui.contexts.dialogAndWindow" name="In Dialog and Windows">
    <children xmi:id="_T7vUOtx5EeOS5eqwaRWLag" elementId="org.eclipse.ui.contexts.window" name="In Windows"/>
    <children xmi:id="_T7vUO9x5EeOS5eqwaRWLag" elementId="org.eclipse.ui.contexts.dialog" name="In Dialogs"/>
  </rootContext>
  <addons xmi:id="_T7vUMtx5EeOS5eqwaRWLag" elementId="org.eclipse.e4.core.commands.service" contributionURI="bundleclass://org.eclipse.e4.core.commands/org.eclipse.e4.core.commands.CommandServiceAddon"/>
  <addons xmi:id="_T7vUM9x5EeOS5eqwaRWLag" elementId="org.eclipse.e4.ui.contexts.service" contributionURI="bundleclass://org.eclipse.e4.ui.services/org.eclipse.e4.ui.services.ContextServiceAddon"/>
  <addons xmi:id="_T7vUNNx5EeOS5eqwaRWLag" elementId="org.eclipse.e4.ui.bindings.service" contributionURI="bundleclass://org.eclipse.e4.ui.bindings/org.eclipse.e4.ui.bindings.BindingServiceAddon"/>
  <addons xmi:id="_T7vUNdx5EeOS5eqwaRWLag" elementId="org.eclipse.e4.ui.workbench.commands.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.CommandProcessingAddon"/>
  <addons xmi:id="_T7vUNtx5EeOS5eqwaRWLag" elementId="org.eclipse.e4.ui.workbench.handler.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon"/>
  <addons xmi:id="_T7vUN9x5EeOS5eqwaRWLag" elementId="org.eclipse.e4.ui.workbench.contexts.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.ContextProcessingAddon"/>
  <addons xmi:id="_T7vUONx5EeOS5eqwaRWLag" elementId="org.eclipse.e4.ui.workbench.bindings.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench.swt/org.eclipse.e4.ui.workbench.swt.util.BindingProcessingAddon"/>
</application:Application>

1 个答案:

答案 0 :(得分:0)

Tom Schindl在Eclipse论坛中回答了这个问题:http://www.eclipse.org/forums/index.php/mv/msg/755949/1371017/#msg_1371017

有两个实例正在构建,因为:

  • OSGi自动实例化一个MPart,因为我已使用DS将其声明为服务;
  • e4自动实例化另一个MPart,因为我已将其定义为应用程序模型中的一部分(e4xmi)。

为了避免这种情况,我考虑了两种方法:

  • 我没有使用DS中的绑定方法,而是在@PostConstruct方法中调用了一个查找所有IWidget的方法:

MainViewPart.java:

private ArrayList<IWidget> widgets;

@PostConstruct
public void postConstruct(Composite parent) {
    lookupWidgets();
}

private void lookupWidgets() throws InvalidSyntaxException {
    widgets = new ArrayList<>();

    BundleContext context = FrameworkUtil.getBundle(this.getClass()).getBundleContext(); 
    Collection<ServiceReference<IWidget>> serviceReferences = context.getServiceReferences(IWidget.class, null);

    for (ServiceReference<IWidget> serviceReference : serviceReferences) {
        IWidget widget = (IWidget) context.getService(serviceReference);
        widgets.add(widget);
    }
}
  • 或者创建另一个包来存储小部件。 MPart将通过DI(依赖注入)在@PostConstruct方法中接收它。

Widget List包中的WidgetList.java:

public class WidgetContainer {

    private ArrayList<IWidget> widgets;

    public WidgetContainer() {
        widgets = new ArrayList<>();
    }

    public void add(IWidget widget) {
        widgets.add(widget);
    }

    public void remove(IWidget widget) {
        widgets.remove(widget);
    }

    public ArrayList<IWidget> getWidgets() {
        return widgets;
    }
}

Widget List包的component.xml(DS):

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="WidgetList">
   <implementation class="br.com.fernandopaz.e4.test.widgetlist.WidgetList"/>
   <reference bind="add" cardinality="1..n" interface="br.com.fernandopaz.e4.test.widget.IWidget" name="IWidget" policy="dynamic" unbind="remove"/>
</scr:component>

主视图部件包中的MainViewPart.java:

private ArrayList<IWidget> widgets;

@PostConstruct
public void postConstruct(Composite parent, WidgetList widgetList) {
    widgets = widgetList.getWidgets();
}