Skip to content

Instantly share code, notes, and snippets.

@tbroyer
Created July 3, 2012 10:07
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tbroyer/3038878 to your computer and use it in GitHub Desktop.
Save tbroyer/3038878 to your computer and use it in GitHub Desktop.
ActivityAsyncProxy
/*
* Copyright 2012 Thomas Broyer <t.broyer@ltgt.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.ltgt.gwt.activity;
import com.google.gwt.activity.shared.Activity;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
/**
* Makes it easy to put any {@link Activity} behind a split-point.
* <p>
* For simple activities, that could be done using an
* {@link com.google.gwt.user.client.AsyncProxy AsyncProxy}, but it's not
* possible for activities created through factories or via dependency
* injection.
* <p>
* As a bonus, the {@link Activity} won't be instantiated at all in case
* the {@link ActivityAsyncProxy} is {@link #onCancel cancelled} before
* the {@link GWT.runAsync async call} returns.
*/
public abstract class ActivityAsyncProxy implements Activity {
private boolean hasAsyncBeenIssued;
private boolean hasAsyncBeenCancelled;
private boolean hasAsyncFailed;
private AcceptsOneWidget display;
private EventBus eventBus;
private Activity instance;
@Override
public String mayStop() {
checkHasAsyncFailed();
assert this.instance != null;
return this.instance.mayStop();
}
@Override
public void onCancel() {
if (this.instance != null) {
this.instance.onCancel();
}
checkHasAsyncFailed();
this.hasAsyncBeenCancelled = true;
}
@Override
public void onStop() {
checkHasAsyncFailed();
assert this.instance != null;
this.instance.onStop();
}
@Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
if (this.instance != null) {
this.instance.start(panel, eventBus);
return;
}
checkHasAsyncFailed();
assert !this.hasAsyncBeenIssued || this.hasAsyncBeenCancelled;
this.display = panel;
this.eventBus = eventBus;
this.hasAsyncBeenCancelled = false;
if (!this.hasAsyncBeenIssued) {
this.hasAsyncBeenIssued = true;
doAsync(new RunAsyncCallback() {
@Override
public void onSuccess() {
if (!ActivityAsyncProxy.this.hasAsyncBeenCancelled) {
assert ActivityAsyncProxy.this.instance == null;
ActivityAsyncProxy.this.instance = createInstance();
ActivityAsyncProxy.this.instance.start(ActivityAsyncProxy.this.display, ActivityAsyncProxy.this.eventBus);
}
}
@Override
public void onFailure(Throwable reason) {
ActivityAsyncProxy.this.hasAsyncFailed = true;
if (GWT.getUncaughtExceptionHandler() != null) {
GWT.getUncaughtExceptionHandler().onUncaughtException(reason);
}
}
});
}
}
/**
* Implementors should simply call {@link GWT#runAsync} here, and nothing else.
* <p>
* This is required to have a different split-point generated for each
* {@link ActivityAsyncProxy} sub-class.
*/
protected abstract void doAsync(RunAsyncCallback callback);
protected abstract Activity createInstance();
private void checkHasAsyncFailed() {
if (this.hasAsyncFailed) {
throw new IllegalStateException("runAsync load previously failed");
}
}
}
@tbroyer
Copy link
Author

tbroyer commented Jul 3, 2012

Example using a GIN Assisted-Inject factory; assuming a factory field in the class (typically an ActivityMapper), and a final String id local variable to pass as argument to the factory (typically extracted from the Place)

// typically found inside your ActivityMapper's getActivity method
return new ActivityAsyncProxy() {
   @Override
   protected void doAsync(RunAsyncCallback callback) {
      GWT.runAsync(callback);
   }
   @Override
   protected Activity createInstance() {
      return factory.employeeActivity(id);
   }
}

@XiX101
Copy link

XiX101 commented Dec 28, 2012

Hi Thomas, in your posts that date a couple of years back, you state that GWT Activities don't support nesting. Has anything changed in this regard; do they support nesting now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment