2012-02-27 66 views
2

我们在GWT项目中使用GIN进行评估,并且通过构造函数参数进行典型注入,结果很好。我们遇到的困难是现场级别的注入。这些字段总是最终为空。有没有人有一个很好的例子,说明如何正确实现GIN提交级别的注入?GWT GIN字段级别注入

更新:

这是与我们相似的一些示例代码:

public class MVP implements EntryPoint { 

    public static final HandlerManager EVENT_BUS = new HandlerManager(null); 
    private final MVPInjector _injector = GWT.create(MVPInjector.class); 

    public void onModuleLoad() { 
    // set up layout for module 
    RootLayoutPanel.get().add(mainPanel); 

    // initialize presenters 
    ListPresenter listPresenter = _injector.listPresenter(); 
    DetailPresenter detailPresenter = _injector.detailPresenter(); 

    listPresenter.go(listContainer); 
    detailPresenter.go(detailContainer); 

    // simulate data coming in from RPC call 
    EVENT_BUS.fireEvent(new DataReadyEvent(getData())); 
    } 
} 

public class ListPresenter { 

    private final HandlerManager _eventBus; 
    private final Map<String, Fruit> _myRecords = new HashMap<String, Fruit>(); 
    private final Display _view; 

    @Inject 
    public ListPresenter(Display argView, HandlerManager argEventBus) { 
    _eventBus = argEventBus; 
    _view = argView; 
    } 

    public void go(HasWidgets argContainer) { 
    argContainer.clear(); 
    argContainer.add(_view.asWidget()); 
    } 

    public interface Display { 
    public Widget asWidget(); 

    public void clear(); 

    public SingleSelectionModel<ViewProxy> getSelectionModel(); 

    public void setData(List<ViewProxy> argData); 
    } 
} 

public class DetailPresenter { 

    private final HandlerManager _eventBus; 
    private final Display _view; 
    private Fruit _myRecord; 

    @Inject 
    private ImagePresenterFactory _imagePresenterFactory; 

    @Inject 
    private TestPresenter _testPresenter; 

    @Inject 
    public DetailPresenter(Display argView, HandlerManager argEventBus) { 
    _view = argView; 
    _eventBus = argEventBus; 
    } 

    public void go(HasWidgets argContainer) { 
    argContainer.clear(); 
    argContainer.add(_view.asWidget()); 

    if (_testPresenter != null) { 
     _testPresenter.go(); 
    } 
    } 

    public interface Display { 
    public Widget asWidget(); 

    public HasText getDescriptionControl(); 

    public HasClickHandlers getImageControl(); 

    public HasText getNameControl(); 

    public HasClickHandlers getSaveControl(); 

    public void setEnabledControls(boolean argEnabled); 
    } 
} 

public class TestPresenter { 

    @Inject 
    HandlerManager _eventBus; 

    public TestPresenter() {} 

    public void go() { 
    if (_eventBus != null) { 
     _eventBus.toString(); 
    } 
    else { 
     // event bus was not injected 
    } 
    } 
} 

@GinModules(MVPModule.class) 
public interface MVPInjector extends Ginjector { 

    DetailPresenter detailPresenter(); 

    ListPresenter listPresenter(); 

} 

public class MVPModule extends AbstractGinModule { 

    @Provides 
    @Singleton 
    public HandlerManager getEventBus() { 
    return MVP.EVENT_BUS; 
    } 

    @Provides 
    public TestPresenter getTestPresenter() { 
    return new TestPresenter(); 
    } 

    @Override 
    protected void configure() { 
    bind(ListPresenter.Display.class).to(ListView.class); 
    bind(DetailPresenter.Display.class).to(DetailView.class); 
    bind(ImagePresenter.Display.class).to(ImagePopup.class); 
    install(new GinFactoryModuleBuilder().build(ImagePresenterFactory.class)); 
    } 

    public interface ImagePresenterFactory { 
    public ImagePresenter createImagePresenter(ImageResource argImage); 
    } 

} 

在上面的代码,我已删除大部分不涉及GIN的代码。 DetailPresenter需要的TestPresenter被成功注入,但TestPresenter要求的HandlerManager始终为空。如您所见,注入的HandlerManager不在构造函数中使用。

+0

而不是试图从构造函数内访问它的值? (很明显,在注入字段之前,对象必须是_constructed_) – 2012-02-27 02:29:12

回答

1

更新,看着示例代码:

@Provides 
public TestPresenter getTestPresenter() { 
    return new TestPresenter(); 
} 

因为你是你自己创造的,它假设你已经经历任何注射。删除这个方法,它会调用默认的构造函数(如果需要,在那里注入),然后访问任何其他注入站点。

您可能遇到的另一个问题:有几个HandlerManager impls,请确保您对HandlerManager的所有引用都使用相同的包。


原来的答复:

他们将构造运行时为空,但是这是有道理的 - 他们怎么可能是其他任何值,当喷射器一直没有机会来分配所有的领域呢。考虑一下这可能会运行(在这里表示为疑似非法的Java,因为字段可能不会是公开的):

InstanceToInject instance = new InstanceToInject(...); 
instance.field = provideFieldValue(); 

由现场甚至有资格被分配的时候,你的构造已经运行。

如果在另一种方法运行时该字段为空,请确保该方法未被构造函数运行,但是在注射完成其工作之后。其他情况下,它可能为空将@Inject注释的制定者。

假设它是没有这些案件(检查最简单的方法是设置一个断点,并确保喷油器是不是在调用栈),可以肯定的是,现场确实有一个@Inject,而且它不是不会绑定到空实例。

+0

我在原始文章中添加了一些示例代码,并澄清了我在哪里获得意外的空值。 – mreynolds0404 2012-02-27 15:31:52

+0

已更新,请查看移除getTestPresenter的建议。如果您出于其他原因需要该方法,那么它需要处理注射 - 这就是@Provides在您使用时的含义。 – 2012-02-28 19:10:03

+0

我明白了;我误解了提供注释的目的。谢谢。 – mreynolds0404 2012-02-29 18:57:55