GWT Code Splitting and Fragments - gwt

In my larg GWT app i tried to split initial download and it happened but I confused in Leftover and exclusive fragments.
Because for example when I use of GWT.runAsync --> onSuccess --> "Window.alert("blob blob");" in onModuleLoad it caused to download a fragment with 1MB size! I think it is other initial fragment, isn't ?
In general my question is how to change leftover or initial fragments to exclusive fragments?
RGDS
Navid

In general with the GWT.runAsync method you can create exclusive fragments or leftovers.
In order to move a piece of code from the initial download to an exclusive fragment, not only you have to use the runAsync method but you also have to make sure that the code in the runAsync method is not referenced in sync parts of your application.
Provided this condition is satisfied, your code can end up in an exclusive fragment (if the code is not used by other runAsync methods) or a leftover (if it is referenced in mulptiple runAsync method).
//Class A is referenced only here!
GWT.runAsync(new RunAsyncCallback() {
#Override
public void onSuccess() {
a = new A();
}
#Override
public void onFailure(Throwable reason) {
...
}
});
....
//Class B is referenced in different points but always inside async calls!
GWT.runAsync(new RunAsyncCallback() {
#Override
public void onSuccess() {
b = new B();
}
#Override
public void onFailure(Throwable reason) {
...
}
});
....
GWT.runAsync(new RunAsyncCallback() {
#Override
public void onSuccess() {
b = new B();
}
#Override
public void onFailure(Throwable reason) {
....
}
});
The code relative to class A will be in an exclusive fragment, class B will be in a leftover.
In general, i suggest you use Compile Reports to understand what's going on in code splitting.
Also: calling runAsync in onModuleLoad doesn't make much sense.
1MB? Are you sure? maybe post an example and I can try to understand what's going on

Code-splitting doesn't work in development mode

Related

SwipeRefreshLayout error

I am trying to implement swiperefreshlayout and I am getting error at "this"
public class viewBets_activity extends ActionBarActivity {
SwipeRefreshLayout swipeLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewbets);
swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
swipeLayout.setOnRefreshListener(this);
swipeLayout.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
}
public void onRefresh() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
swipeLayout.setRefreshing(false);
}
}, 5000);
}
}
I am getting error at swipeLayout.setOnRefreshListener(this); screenshot below
Well, now that you added the screenshot, the error is clear.
You're passing the wrong argument into setOnRefreshListener()! And of course, this makes sense, if you think about it. Your class is a ActionBarActivity. You're trying to set the OnRefreshListener as an ActionBarActivity...doesn't make any sense! You need to change your code to this:
swipeLayout.setOnRefreshListener(new OnRefreshListener()
{
#Override
public void onRefresh()
{
// what you want to happen onRefresh goes here
}
});
Here, you're creating a new OnRefreshListener object which you're adding as the listener.
For the future, in general, any time you have a setOn______Listener() method, the argument you'll be passing will be a On_____Listener object that you've customized. You can either created separately, or create it right in the set method the way I did in my answer.
Your class is missing
implement SwipeRefreshLayout.OnRefreshListener
This allows the listener to refer to the overridden method onRefresh when passing through this as the argument for setOnRefreshListener

GWT - run command exactly once per event loop

I'm writing some wrapper classes around zurb foundation.
Foundation widgets need an init() function to be called after the elements have been added to the DOM.
I can accomplish this easily enough with this method:
public static void initWidgets() {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
foundationInit();
}
});
}
...where foundationInit() is a JSNI call to the foundation init() function. I then add a call to initWidgets() in the constructor of any foundation element. So far so good.
However, if multiple foundation widgets are added to the DOM during a particular event loop, then the init() method will be called multiple times. Foundation doesn't actually care about this, but it would be nice to find a way around this.
Is there any scheduler functionality / pattern that'd allow me to schedule a particular command to run only once, no matter how many times the schedule method is called with that command?
Something like: scheduleDeferredIfNotAlreadyScheduled(Command c)
I don't know how to get a handle on the event loop, so I don't know how to reset a flag that'd tell me whether or not to add the command or not.
I don't know any Scheduller command to do that, but it could be done with a static boolean variable, e.g.:
private static boolean initialized;
public static void initWidgets() {
initialized = false;
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
if (!initialized) {
initialized = true;
foundationInit();
}
}
});
}
In such case I usually use Guava's Supplier.double checked locking is really safe.
public static Supplier<Boolean> supplier=Suppliers.memoize(new Supplier<Boolean>() {
#Override
public Boolean get() {
foundationInit();
return true;
}
});
public static void initWidgets() {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
boolean initialized=supplier.get();
}
});
}

How to call GWT client code from within a GQuery event handler?

I'm learning GQuery. It seems cool, but also a little confusing.
I have the following GWT client code. The selected item fades out, nicely. But the delete method never gets called. There is no error. It's very odd.
Is it even possible to call non-GQuery functions from inside a GQuery method?
delete.addClickHandler( new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
$(myIndicator).fadeOut(500, new Function(){
#Override
public void f() {
super.f();
delete();
}
});
}
});
And the delete method is:
private void delete() {
removeFromParent();
ruleDeleteRequestEvent.fire(new RuleDeleteRequestEvent(ruleBinder.getModel()));
}
Do not call super.f(), if so the default implementation of Function.f() will throw an Exception preventing the next line be executed (take a look to the source code) .

GWT Shared Entry Point with iPhone UIWebView

I have an app which works fine at the moment and uses geolocation. I have a method which calls com.google.gwt.geolocation.client.Geolocation.
I extended the existing entry point and overriden this method to use the native Geolocation library so I don't have any permission popups.
How can I avoid having two modules which takes twice as long to compile?
In GWT normally you have an entry-point per application, or perl .html page, but you can have other scenarios: you could have a module file (.gwt.xml) with multiple entry-points, or a page loading multiple modules (.cache.js), or even you could load the same module (.cache.js) in different pages.
So, in your case, you could maintain one entrypoint and one module file and include the same compiled module in both pages. In this case you have to write some code in your entry point to know what to do in each page:
public void onModuleLoad() {
if (Window.Location.getPath().matches(".*page_1.html.*")) {
// do something
} else {
// do another thing
}
}
Think that in this case you will have all the compiled stuff in both pages, but you could take advantage of gwt code-splitting and make each page load just the stuff it needs:
public void onModuleLoad() {
if (Window.Location.getPath().matches(".*page_1.html.*")) {
GWT.runAsync(new RunAsyncCallback() {
public void onSuccess() {
// do something
}
public void onFailure(Throwable reason) {
}
});
} else {
GWT.runAsync(new RunAsyncCallback() {
public void onSuccess() {
// do another thing
}
public void onFailure(Throwable reason) {
}
});
}
}
The advantages of this approach is that you compile just once for all your site, and you share the same code in all your pages taking advantage of the cache. There are disadvantages as well like your final code is higher, dev-mode could be slower, etc.

How to intercept the onSuccess() method in GWT

I need to do method interception for the onSuccess method in GWT.
I need to add some code before and after the calling of the onSuccess method in GWT? (I have many calls to the onSuccess method and I need to do this dynamically)
EDIT:
I need to add a progress bar in the right corner of the screen, that appears when the code enters the onsuccess method and disappears on the exit of onsuccess method.
From a visual perspective
void onSuccess(Value v) {
showProgressBar();
doLotsOfWork(v);
hideProgressBar();
}
will be a no-op. Browsers typically wait for event handlers to finish executing before re-rending the DOM. If the doLotsOfWork() method takes a noticeable amount of time to execute (e.g. >100ms) the user will notice the browser hiccup due to the single-threaded nature of JavaScript execution.
Instead, consider using an incrementally-scheduled command to break the work up. It would look roughly like:
void onSuccess(Value v) {
showProgressBar();
Scheduler.get().scheduleIncremental(new RepeatingCommand() {
int count = 0;
int size = v.getElements().size();
public boolean execute() {
if (count == size) {
hideProgressBar();
return false;
}
processOneElement(v.getElements().get(count++));
setProgressBar((double) count / size);
return true;
}
});
}
By breaking the work across multiple pumps of the browser's event loop, you avoid the situation where the webapp becomes non-responsive if there's a non-trivial amount of work to do.
Well, it is a generic non-functional requirement, I have done some research on this item, I have implemented a solution that Thomas Broyer has suggested on gwt group.. This solution has distinct advantage over other suggested solutions, You dont have to change your callback classes, what you have to do is just add a line of code after creation of async gwt-rpc service...
IGwtPersistenceEngineRPCAsync persistenceEngine = GWT.create(IGwtPersistenceEngineRPC.class);
((ServiceDefTarget) persistenceEngine).setRpcRequestBuilder(new ProgressRequestBuilder());
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.Response;
import com.google.gwt.user.client.rpc.RpcRequestBuilder;
public class ProgressRequestBuilder extends RpcRequestBuilder {
private class RequestCallbackWrapper implements RequestCallback {
private RequestCallback callback;
RequestCallbackWrapper(RequestCallback aCallback) {
this.callback = aCallback;
}
#Override
public void onResponseReceived(Request request, Response response) {
Log.debug("onResposenReceived is called");
// put the code to hide your progress bar
callback.onResponseReceived(request, response);
}
#Override
public void onError(Request request, Throwable exception) {
Log.error("onError is called",new Exception(exception));
// put the code to hide your progress bar
callback.onError(request, exception);
}
}
#Override
protected RequestBuilder doCreate(String serviceEntryPoint) {
RequestBuilder rb = super.doCreate(serviceEntryPoint);
// put the code to show your progress bar
return rb;
}
#Override
protected void doFinish(RequestBuilder rb) {
super.doFinish(rb);
rb.setCallback(new RequestCallbackWrapper(rb.getCallback()));
}
}
You cant do that. The rpc onSuccess() method runs asynchronously (in other words, depends on the server when it completes, the app doesnt wait for it). You could fire code immediately after the rpc call which may/ may not complete before the onSuccess for RPC calls.
Can you explain with an eg why exactly do u want to do that? Chances are you might have to redesign the app due to this async behavior, but cant say till you provide a use case. Preferably any Async functionality should be forgotten after the rpc call, and actioned upon only in the onSuccess.