Ah, well I'd be interested to see what you come up with as far as
reducing the boilerplate.

I had tried a few different scenarios, but I found that unless the
actual call to GWT.runAsync for each proxied Presenter was in a unique
class then the compiler wouldn't split out the code properly. I'm
guessing the code-splitting mechanism in the compiler pivots at least
in part on the class containing the call.

On Feb 9, 4:14 pm, Joe Cheng <[email protected]> wrote:
> OK, great, I went through a similar approach previously. The new approach
> I'm using is similar but you can remove the boilerplate in the proxy
> implementation, as the deferred binding mechanism will fill it all in. In
> fact since you're using Gin it will literally look like this:
>
> public abstract class MyAsyncShim extends AsyncShim<MyPresenter> { }
>
> I'll reply to this thread when I have something written up. I would also
> like to adapt your idea of using a command queue, right now I'm doing
> something similar but not guaranteeing the methods will be executed in the
> order they were invoked.
>
>
>
> On Tue, Feb 9, 2010 at 8:42 AM, jarrod <[email protected]> wrote:
> > Joe,
>
> > In fact, no it does not work properly with multiple instances, and
> > this is a problem I discovered shortly after originally posting this.
> > The solution I devised was to make the Proxy abstract and simply
> > create concrete sub-classes for each Presenter I want to proxy
> > (anonymous sub-classes do not work!). This is a little tedious, but
> > the abstraction I wrote makes it pretty simple to implement. Below is
> > the updated code. Note that I also changed the ViewProxy to use a
> > LayoutPanel instead of a SimplePanel so that proxied views that
> > implement RequiresLayout are supported.
>
> > /**
> >  * PresenterProxy wraps a Presenter implementation and acts as a
> > gateway to that
> >  * Presenter. The wrapped Presenter is created on-demand the first
> > time any
> >  * method is called, or optionally it can be created eagerly at the
> > time the
> >  * PresenterProxy is created.
> >  *
> >  * Instantiation of the wrapped Presenter occurs behind a
> > GWT.runAsync() call so
> >  * that complex wrapped Presenters may be split out into code
> > fragments during
> >  * module compilation.
> >  *
> >  * In order to achieve this "delayed" instantiation, the
> > PresenterProxy must be
> >  * given a Provider<T extends Presenter> instance to provide the
> > actual
> >  * implementation at the appropriate time.
> >  *
> >  * Additionally, a ViewProxy is utilized that consists of a
> > LayoutPanel to
> >  * minimize the impact on the UI. The ViewProxy can be inserted into
> > the DOM
> >  * immediately without waiting for the wrapped Presenter to become
> > available.
> >  *
> >  * Any calls made to the wrapped Presenter before the instance becomes
> > available
> >  * are queued in a buffer and later replayed when the instance becomes
> >  * available. Once available, all calls are executed immediately on
> > the wrapped
> >  * instance.
> >  *
> >  * @author jcarlson
> >  *
> >  * @param <T>
> >  */
> > public abstract class PresenterProxy<T extends Presenter> implements
> >         Presenter {
>
> >    private static class ProxyView implements View {
>
> >         LayoutPanel proxy = new LayoutPanel();
>
> >        ProxyView() {
> >        }
>
> >       �...@override
> >        public Widget asWidget() {
> >            return this.proxy;
> >        }
>
> >        protected void setView(View view) {
> >             this.proxy.clear();
> >            this.proxy.add(view.asWidget());
> >         }
>
> >    }
>
> >    private boolean asyncCalled;
> >    private boolean bound;
>
> >    private HandlerManager bus;
> >    private T impl;
> >     private Queue<Command> queue;
> >    private ProxyView view;
>
> >     public PresenterProxy(HandlerManager bus) {
> >        this(bus, false);
> >    }
>
> >    public PresenterProxy(HandlerManager bus, boolean eager) {
> >        this.bus = bus;
> >         this.queue = new LinkedList<Command>();
> >        this.view = new ProxyView();
> >        if (eager) {
> >            ensurePresenter();
> >        }
> >    }
>
> >   �...@override
> >     public final void bind() {
> >         this.bound = true;
> >        queue(new Command() {
>
> >           �...@override
> >            public void execute() {
> >                 PresenterProxy.this.impl.bind();
> >            }
>
> >        });
> >    }
>
> >   �...@override
> >    public final View getView() {
> >        return this.view;
> >    }
>
> >   �...@override
> >    public final void handleHistory(final HistoryItem item) {
> >         queue(new Command() {
>
> >           �...@override
> >            public void execute() {
> >                 PresenterProxy.this.impl.handleHistory(item);
> >            }
>
> >        });
> >    }
>
> >   �...@override
> >    public final boolean isBound() {
> >        return this.bound;
> >    }
>
> >   �...@override
> >    public final void release() {
> >         queue(new Command() {
>
> >           �...@override
> >            public void execute() {
> >                 PresenterProxy.this.impl.release();
> >            }
> >        });
> >        this.bound = false;
> >    }
>
> >    protected final void onAsyncFailure(Throwable reason) {
> >        PresenterProxy.this.bus
> >                .fireEvent(new ApplicationExceptionEvent(reason));
> >    }
>
> >    protected final void onAsyncSuccess(T impl) {
> >        // set impl instance
> >        this.impl = impl;
>
> >        // fill-in proxy view
> >        this.view.setView(PresenterProxy.this.impl.getView());
>
> >        // execute any queued commands
> >        while (ResizingPresenterProxy.this.queue.peek() != null) {
> >            Command cmd = PresenterProxy.this.queue.poll();
> >            cmd.execute();
> >        }
>
> >    }
>
> >    /**
> >     * The key method that subclasses must override.
> >     * This allows each GWT.runAsync() call to be in its own
> >     * concrete class, thus allowing the compiler to produce
> >     * multiple exclusive fragments.
> >     */
> >    protected abstract void runAsync();
>
> >    void ensurePresenter() {
> >        if (!this.asyncCalled) {
> >            this.asyncCalled = true;
> >             runAsync();
> >         }
> >    }
>
> >    void queue(Command command) {
> >        ensurePresenter();
> >        if (this.impl != null) {
> >            command.execute();
> >        } else {
> >            this.queue.offer(command);
> >        }
> >    }
>
> > }
>
> > And an implementation of the proxy:
>
> > public class MyPresenterProxy extends
> >        PresenterProxy<ProfilePresenter> {
>
> >    private Provider<ProfilePresenter> provider;
>
> >   �...@inject
> >    public MyPresenterProxy(HandlerManager bus,
> >            Provider<ProfilePresenter> provider) {
> >        super(bus);
> >        this.provider = provider;
> >    }
>
> >   �...@override
> >    protected void runAsync() {
> >         GWT.runAsync(new RunAsyncCallback() {
>
> >           �...@override
> >            public void onFailure(Throwable reason) {
> >                 onAsyncFailure(reason);
> >            }
>
> >           �...@override
> >            public void onSuccess() {
> >                MyPresenter presenter = MyPresenterProxy.this.provider
> >                        .get();
> >                onAsyncSuccess(presenter);
> >            }
> >        });
> >     }
>
> > }
>
> > On Feb 8, 3:31 am, Joe Cheng <[email protected]> wrote:
> > > Jarrod, are you using this ProxyPresenter more than once within the same
> > > application (with different presenter type parameters), and found that it
> > > introduced the split points as expected? I originally tried something
> > like
> > > this but found that it would only ever introduce a single split point, no
> > > matter how many times I used it.
>
> > > I was able to solve the problem using deferred binding and was about to
> > > write a blog post about it, but if your code actually works as desired
> > then
> > > I need to go back and figure out what I was doing wrong.
>
> > > On Mon, Jan 25, 2010 at 8:16 PM, jarrod <[email protected]>
> > wrote:
> > > > 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...
>
> read more »

-- 
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.

Reply via email to