4

我按照本教程的建议实现了一个 GWT 应用程序。我还下载了示例代码,我注意到演示的每个 Presenter 都需要注入到主 Presenter 构造函数中才能被实例化。作者在源代码中包含了这一点:

public class GreetingPresenter extends WidgetPresenter<GreetingPresenter.Display> {

    // FUDGE FACTOR!  Although this is not used, having GIN pass the object
    // to this class will force its instantiation and therefore will make the
    // response presenter listen for events (via bind()).  This is not a very good way to
    // achieve this, but I wanted to put something together quickly - sorry!
    private final GreetingResponsePresenter greetingResponsePresenter;

    @Inject
    public GreetingPresenter(final Display display, final EventBus eventBus, final DispatchAsync dispatcher, final GreetingResponsePresenter greetingResponsePresenter) {
            super(display, eventBus);       
            this.dispatcher = dispatcher;       
            this.greetingResponsePresenter = greetingResponsePresenter;     
            bind();
}

我验证了如果没有在 GreetingPresenter 中注入任何 Presenter,它将不会被实例化。出于演示目的,这很酷,因为整个应用程序只有两个 Presenter,但在真实世界的应用程序中,这可能会带来严重的不便。

完成 Presenter 实例化的正确方法是什么?

编辑:包括 GIN 相关类以供参考:

演讲者模块:

public class GreetingClientModule extends AbstractPresenterModule {

    @Override
    protected void configure() {        
        bind(EventBus.class).to(DefaultEventBus.class).in(Singleton.class);
        bind(PlaceManager.class).in(Singleton.class);       
        bindPresenter(GreetingPresenter.class, GreetingPresenter.Display.class, GreetingView.class);
        bindPresenter(GreetingResponsePresenter.class, GreetingResponsePresenter.Display.class, GreetingResponseView.class);        
        bind(AppPresenter.class).in(Singleton.class);
        bind(CachingDispatchAsync.class);
    }
}

注射器:

@GinModules({ ClientDispatchModule.class, GreetingClientModule.class })
public interface GreetingGinjector extends Ginjector {

    AppPresenter getAppPresenter();
    PlaceManager getPlaceManager();

}
4

2 回答 2

3

您可以使用 Providers 来解决这个问题。在我的 Gin Modules 中,我声明了我的 Presenter/Activity 以及它的视图,如下所示

    // Content Area
    bind(ContentActivityMapper.class).in(Singleton.class);

    // Intro Page
    bind(IntroPageActivity.class);
    bind(IntroPageView.class).to(IntroPageViewImpl.class).in(Singleton.class);

然后在 Activity Mapper 我使用这样的提供者

public class ContentActivityMapper implements ActivityMapper {

    @Inject Provider<IntroPageActivity> introPageProvider;

    public Activity getActivity(Place place) {

        if (place instanceof DefaultPlace) {
        return introPageProvider.get().withPlace(new IntroPagePlace());
        }...

我在 ActivityPresenter 上设置了 withPlace 方法,以允许在没有参数的情况下注入它。该代码看起来像这样。

public class IntroPageActivity extends AbstractActivity {

    private IntroPageView view;

    @Inject
    public IntroPageActivity(IntroPageView view) {
        super();
        this.view = view;
    }

    public IntroPageActivity withPlace(IntroPagePlace place) {
        return this;
    }

    @Override
    public void start(AcceptsOneWidget containerWidget, EventBus eventBus) {
        containerWidget.setWidget(view.asWidget());
    }...
于 2012-04-13T15:08:47.110 回答
2

我认为您缺少 Ginjector 和 AbstractGinModule 定义,您在其中定义了该示例中的 GIN 绑定。
我建议从提到的教程下载代码,并查看 GIN 入门wiki

GreetingGinjector :

@GinModules({ ClientDispatchModule.class, GreetingClientModule.class })
public interface GreetingGinjector extends Ginjector {

    AppPresenter getAppPresenter();

    PlaceManager getPlaceManager();

}

问候客户端模块

public class GreetingClientModule extends AbstractPresenterModule {

    @Override
    protected void configure() {        
        bind(EventBus.class).to(DefaultEventBus.class).in(Singleton.class);
        bind(PlaceManager.class).in(Singleton.class);

        bindPresenter(GreetingPresenter.class, GreetingPresenter.Display.class, GreetingView.class);
        bindPresenter(GreetingResponsePresenter.class, GreetingResponsePresenter.Display.class, GreetingResponseView.class);

        bind(AppPresenter.class).in(Singleton.class);
        bind(CachingDispatchAsync.class);
    }
}

入口点

public class GreetMvp implements EntryPoint {
    private final GreetingGinjector injector = GWT.create(GreetingGinjector.class);

    public void onModuleLoad() {
        final AppPresenter appPresenter = injector.getAppPresenter();
        appPresenter.go(RootPanel.get());

        injector.getPlaceManager().fireCurrentPlace();
    }
}
于 2012-04-12T20:33:21.430 回答