While building an application for my company, I needed a way to make
large sections of the application sit behind a split point. After
organizing my application into "modules" of related functionality, I
came up with slick, easy way to make those "modules" split out
automatically: by using a proxy presenter.
My application uses gin and a hand-made MVP framework based loosely
off of gwt-presenter. Some adaptation may be necessary to fit your
particular frameworks, but here goes:
public class ProxyPresenter<T extends Presenter> implements Presenter
{
private static class ProxyView implements View {
SimplePanel proxy = new SimplePanel();
ProxyView() {
}
@Override
public Widget asWidget() {
return this.proxy;
}
protected void setView(View view) {
this.proxy.setWidget(view.asWidget());
}
}
private boolean asyncCalled;
private boolean bound;
private HandlerManager bus;
private T impl;
private Provider<T> provider;
private Queue<Command> queue;
private ProxyView view;
public ProxyPresenter(HandlerManager bus, Provider<T> provider) {
this(bus, provider, false);
}
public ProxyPresenter(HandlerManager bus, Provider<T> provider,
boolean eager) {
this.bus = bus;
this.provider = provider;
this.queue = new LinkedList<Command>();
this.view = new ProxyView();
if (eager) {
ensurePresenter();
}
}
@Override
public void bind() {
this.bound = true;
queue(new Command() {
@Override
public void execute() {
ProxyPresenter.this.impl.bind();
}
});
}
@Override
public View getView() {
return this.view;
}
@Override
public void handleHistory(final HistoryItem item) {
queue(new Command() {
@Override
public void execute() {
ProxyPresenter.this.impl.handleHistory(item);
}
});
}
@Override
public boolean isBound() {
return this.bound;
}
@Override
public void release() {
queue(new Command() {
@Override
public void execute() {
ProxyPresenter.this.impl.release();
}
});
this.bound = false;
}
protected void ensurePresenter() {
if (!this.asyncCalled) {
this.asyncCalled = true;
GWT.runAsync(new RunAsyncCallback() {
@Override
public void onFailure(Throwable reason) {
ProxyPresenter.this.bus
.fireEvent(new ApplicationExceptionEvent
(reason));
}
@Override
public void onSuccess() {
// get impl instance
ProxyPresenter.this.impl =
ProxyPresenter.this.provider
.get();
// fill-in proxy view
ProxyPresenter.this.view.setView
(ProxyPresenter.this.impl
.getView());
// execute any queued commands
while (ProxyPresenter.this.queue.peek() != null) {
Command cmd = ProxyPresenter.this.queue.poll
();
cmd.execute();
}
}
});
}
}
protected void queue(Command command) {
ensurePresenter();
if (this.impl != null) {
command.execute();
} else {
this.queue.offer(command);
}
}
T getPresenter() {
return this.impl;
}
}
Then, in my gin module, instead of using an explicit bind, I use a
@Provides method, like so:
@Provides
Presenter getRealPresenter(HandlerManager bus,
Provider<RealPresenter> provider) {
return new ProxyPresenter<RealPresenter>(bus, provider);
}
The rest is automagic!
--
You received this message because you are subscribed to the Google Groups
"Google Web Toolkit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-web-toolkit?hl=en.