Skip to content

Instantly share code, notes, and snippets.

@jcheng5
Created February 17, 2010 06:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcheng5/306366 to your computer and use it in GitHub Desktop.
Save jcheng5/306366 to your computer and use it in GitHub Desktop.
package com.joecheng.asyncshim.client;
import com.google.gwt.user.client.Command;
import com.google.inject.Inject;
import com.google.inject.Provider;
/**
* AsyncShim makes it easy to sequester a class behind GWT.runAsync()
* and cause it to be lazy-loaded, while still making it convenient to
* call (some types of) methods on it from other parts of the code that
* are not in the same fragment.
*
* For each type that needs to be sequestered, create an *abstract*
* AsyncShim subclass with the TTarget type parameter set to the
* sequestered type. (The AsyncShim subclass must be at package-level
* or public visibility.)
*
* In your AsyncShim subclass, you'll want to override onDelayLoadSuccess
* and onDelayLoadFailure to do whatever your app needs. onDelayLoadSuccess
* will be called only once, when the instance of TTarget is first created.
*
* You can also add any other fields, methods, etc. to your subclass that
* are necessary to give onDelayLoadSuccess and/or onDelayLoadFailure any
* contextual state they need.
*
* As mentioned, AsyncShim can make some kinds of methods easy to call from
* other fragments. Specifically, any method that returns void and
* semantically makes sense to run asynchronously, can be easily passed
* through AsyncShim. Just stub out an abstract version of the method on
* your AsyncShim subclass, and deferred binding will take care of wiring
* everything up. Or, you can have your AsyncShim subclass "implement" an
* interface but not actually provide implementations--if these methods
* return void, they will also be automatically wired up.
*
* @param <TTarget> The type to be sequestered
*/
public abstract class AsyncShim<TTarget>
{
/**
* [DON'T override this, it will be overridden by the code generator]
*
* This method must be called (either automatically via Gin injection, or
* the old-fashioned way) before the target object is needed.
*/
@Inject
public void initialize(Provider<TTarget> provider)
{
}
public final void forceLoad(boolean downloadCodeOnly)
{
forceLoad(downloadCodeOnly, null);
}
/**
* [DON'T override this, it will be overridden by the code generator]
*
* Call this to force the code to be downloaded, and optionally, for
* the provider to be invoked
*
* @param downloadCodeOnly If true, the code will be downloaded but
* the provider will not be invoked
* @param continuation A command to invoke after the load is complete
* (regardless of whether the effort was successful or not). Can be
* null.
*/
public void forceLoad(boolean downloadCodeOnly, Command continuation)
{
}
/**
* You can override this to do something with the delayed type once the
* code loads and the instance is created.
* @param obj
*/
protected void onDelayLoadSuccess(TTarget obj)
{
}
/**
* You can (should!) override this to deal with failure cases.
* @param reason
*/
protected void onDelayLoadFailure(Throwable reason)
{
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment