are GWT 2.1.1 Activities expensive to create/instantiate ?

79 views
Skip to first unread message

zixzigma

unread,
Jan 7, 2011, 11:11:34 PM1/7/11
to Google Web Toolkit
Are GWT 2.1.1 Activities expensive to create ?

Activities are managed by ActivityManagers.
ActivityManagers call "start" method on Activities so that Activities
can start doing their work.
Activities do majority of their work in their start method, for
example communicating with the server,
populating views with data and so on.

having said all these,
Activities can take PlaceController, Place, Presenter objects in their
constructors.
therefore even if they are not "Started" by the ActivityManager, just
instantiation of them can be costly.

is this true ?

my main concern is this:

lets say an application has 150 activities.
and application is configured in such a way in GIN,
that all of application activities are injected in a provider
on application startup.
therefore all of the 150 activities are instantiated,
however they are not started yet (activitymanager has not called the
start on them).

I want to know whether this early eagerly instantiation is expensive
and will bring down the application ?

if the activities were "Started" on startup, which resulted in
contacting server for data, I can imagine it can become slow as
application grows.

Do you think even the instantiation of activities is expensive ?
consideriing an Activity has a Place, PlaceController, a View and a
few Presenters.
(therefore activities have dependency of their own)

Thank You

Gal Dolber

unread,
Jan 7, 2011, 11:31:43 PM1/7/11
to google-we...@googlegroups.com
In theory: no.
The heavy part is the view. If you instantiate 150 activities without instantiating the views you wont have problems.
The best you can do is benchmark it.

Best



--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.




--
Guit: Elegant, beautiful, modular and *production ready* gwt applications.

http://code.google.com/p/guit/




Thomas Broyer

unread,
Jan 8, 2011, 6:01:54 AM1/8/11
to google-we...@googlegroups.com
You shouldn't instantiate activities at "startup", and you shouldn't reuse an activity instance. The idea of GWT activities is that they are cheap to instantiate (contrary to views, because of DOM manipulations) so you instantiate one each time the ActivityManager is asked to provide it.
Using GIN, it means you'd @Inject Provider<?>s (or factories if you want to pass arguments, such as Place-specific values: for instance, the ID of the object to be edited) for your activities into your ActivityManager (so that an activity is instantiated each time you call the Provider's get() method), and you won't annotate the activities with @Singleton (but you would bind views as singletons, to do the heavy work once only per view).
That way, the first time an activity is needed, its dependencies are initialized also (i.e. the view is created / the placeController is already initialized so it's provided directly and it's a no-op), and this can be "a bit of work" (instantiating the view, which involves "heavyweight" DOM manipulations). Next time you need an instance of the same activity type, dependencies (which are likely to all be singletons) are already initialized and creating the activity is very cheap (you shouldn't do much work in the constructor, just store the dependencies in fields so you'll use them later, waiting forthe start() method to be called).

zixzigma

unread,
Jan 8, 2011, 3:23:22 PM1/8/11
to Google Web Toolkit

On Jan 8, 3:01 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> Using GIN, it means you'd @Inject Provider<?>s [.... ] for your activities into your ActivityManager (so that
> an activity is instantiated each time you call the Provider's get() method),

- do you mean injecting providers into "ActivityMappers" ? or
"ActivityManagers" ?

- your comment on Provider vs Factories
just to make sure if I understood your correctly,
if we have a Provider and want to pass Activity specific parameters
to it,
this would not be possible with GIN Providers, right ?
because GIN Providers have one get() methods, and not possible to pass
parameters.
that is why we have to use Factories instead of GIN Providers?

- following on a related question I asked in another post,[1]
lets say we are keeping a map of all of our application activities,
which is @injected
in a class(Registry) at application startup through a GIN Provider
that puts all activity instances in that map;
this approach would result in early instantiation of all activities.
right ?

if we instead relied on ActivityProviders, and keeping a map of all of
our ActivityProviders instead (rather than activity instances
themselves),
it appears we are deferring the early instantiation of Activities.
But injecting ActivityProviders will result in Activity Instantiation,
for example in the code below,
if we @Inject MyActivityProvider at startup in a class, MyActivity is
alo instantiated right away, right ? (constructor injection)

in cases where we have 150 Activities, for each of them an
ActivityProvider, therefore 150 ActivityProviders, (somehow organized)
and injecting these ActivityProviders upfront in a class(registry) at
application startup, will it result in rightaway instantiation of all
our Activities as well ?

// we are defining an ActivityProvider for each of our Activities
public class MyActivityAProvider implements Provider<MyActivityA> {

private final MyActivityA myActivityA;

@Inject
MyActivityAProvider(MyActivityA myActivityA){
this.myActivityA = myActivityA;
}

MyActivityA get(){

return myActivityA;
}

}

https://groups.google.com/group/google-web-toolkit/browse_thread/thread/00a5e77a84b29202/bdf104ac34ac16db?hl=en#bdf104ac34ac16db

Thomas Broyer

unread,
Jan 8, 2011, 5:19:19 PM1/8/11
to google-we...@googlegroups.com


On Saturday, January 8, 2011 9:23:22 PM UTC+1, zixzigma wrote:

On Jan 8, 3:01 am, Thomas Broyer <t.br...@gmail.com> wrote:
> Using GIN, it means you'd @Inject Provider<?>s [.... ] for your activities into your ActivityManager (so that
> an activity is instantiated each time you call the Provider's get() method),

- do you mean injecting providers into "ActivityMappers" ? or
"ActivityManagers" ?

ActivityMapper-s yes, sorry.
 
- your comment on Provider vs Factories
just to make sure if I understood your correctly,
if we have a Provider and  want to pass Activity specific parameters
to it,
this would not be possible with GIN Providers, right ?
because GIN Providers have one get() methods, and not possible to pass
parameters.
that is why we have to use Factories instead of GIN Providers?

Yes. A Provider gives you an instance with all dependencies injected. A factory allows you to further parameterize the instance (and if you use some snapshot of GIN, you have access to AssistedInject so you don't have to code your factories, just define their API through an interface)

- following on a related question I asked in another post,[1]
lets say we are keeping a map of all of our application activities,
which is @injected
in a class(Registry) at application startup through a GIN Provider
that puts all activity instances in that map;
this approach would result in early instantiation of all activities.
right ?

If you put activity instances, yes.

(remember, GIN generates Java code that's compiled by the GWT compiler –just like any other generator–, that means this is code you could have written yourself, so each time you get an instance from GIN, you can quickly imagine which kind of code you would have written yourself to initialize it. As I like to say: there's no magic!)

if we instead relied on ActivityProviders, and keeping a map of all of
our ActivityProviders instead (rather than activity instances
themselves),
it appears we are deferring the early instantiation of Activities.

Yes.
 
But injecting ActivityProviders will result in Activity Instantiation,
for example in the code below,
if we @Inject MyActivityProvider at startup in a class, MyActivity is
alo instantiated right away, right ? (constructor injection)

The way you wrote it, yes (and it's therefore totally useless).

in cases where we have 150 Activities, for each of them an
ActivityProvider, therefore 150 ActivityProviders, (somehow organized)
and injecting these ActivityProviders upfront in a class(registry) at
application startup, will it result in rightaway instantiation of all
our Activities as well ?

Yes, of course.

// we are defining an ActivityProvider for each of our Activities
public class MyActivityAProvider implements Provider<MyActivityA> {

What's the point in implementing Provider yourself?

zixzigma

unread,
Jan 8, 2011, 8:28:07 PM1/8/11
to Google Web Toolkit
> What's the point in implementing Provider yourself?

is there a way to not implement the Provider myself ?
through GIN's assisted inject ?

> The way you wrote it, yes (and it's therefore totally useless).

you are correct, the way I wrote it, wouldnt defer instantiation of
activities,
so it is useless.

however if I instead use a Factory

public class MyActivityFactory implements
AppActivityFactory<MyActivity> {

MyActivity getActivity(){

return new MyActivity();
}

}

this way, I can defer the instantiation of MyActivity until the time
it is actually requested.
and I can pass in other dependencies to MyActivity from this
MyActivityFactory.

my goal is to have a registry to hold all activities that are used in
the application.
to avoid early instantiation of activities.
From your comments I realized it might be better
to keep a map of ActivityFactories instead of Activity instances,
so that upon request, these ActivityFactories can supply the
appropriate Activity.

I am not sure however having an ActivityFactory for each Activity, is
a good idea,
because with 150 Activities, having 150 ActivityFactories might be too
much.
is there a better/alternative way ?

and I intend to further expand these ActivityFactories to help in
CodeSplitting,
through AsyncProxyProvider.


therefore this is the reason I was planning to use one Provider per
Activity, now I am going to use
one Factory per Activity.

but you hinted on GIN assisted inject. could you please elaborate a
little on that ?
and in your opinion is the idea behind using ActivityFactory flawed ?
can you think of an alternative approach or suggest a way to improve
what I'm trying to achieve ?


Thank You

Thomas Broyer

unread,
Jan 9, 2011, 6:12:17 AM1/9/11
to google-we...@googlegroups.com


On Sunday, January 9, 2011 2:28:07 AM UTC+1, zixzigma wrote:
> What's the point in implementing Provider yourself?

is there a way to not implement the Provider myself ?
through GIN's assisted inject ?

The whole idea of Provider is that Guice/GIN implement them!
You only have to "ask" for it and GIN will provide it, e.g.
@Inject
MyObject(SomeObject thisWillBeAnInitializedInstance, Provider<SomeObject> thisWillBeAProvider) {
...
}

Then, depending on the scope you bound your type to (in GIN, limited to singleton or not), the provider will either always return the same instance (initializing it once the first time you call the provider's get() method) or a new instance each time (Provider acting like a factory, without the possibility to parameterize the object).

Assisted-inject is something else: you can define a factory interface (will methods taking arguments) and GIN will implement them, mixing dependency injection with the values you passed to the method.
 
> The way you wrote it, yes (and it's therefore totally useless).

you are correct, the way I wrote it, wouldnt defer instantiation of
activities,
so it is useless.

however if I instead use a Factory

public class MyActivityFactory implements
AppActivityFactory<MyActivity> {

MyActivity getActivity(){

 return new MyActivity();
}

}

this way, I can defer the instantiation of MyActivity until the time
it is actually requested.
and I can pass in other dependencies to MyActivity from this
MyActivityFactory.

But you then have to maintain the dependencies that you'd manually inject into the activity's constructor. And to be sure you respect the scopes, you need similar "factories" for each dependency.
You'e just re-invented the Provider.

my goal is to have a registry to hold all activities that are used in
the application.
to avoid early instantiation of activities.
From your comments I realized it might be better
to keep a map of ActivityFactories instead of Activity instances,
so that upon request, these ActivityFactories can supply the
appropriate Activity.

I am not sure however having an ActivityFactory for each Activity, is
a good idea,
because with 150 Activities, having 150 ActivityFactories might be too
much.
is there a better/alternative way ?

If you don't need to pass arguments, then just inject Provider<MyActivity> instead of Activity and you have a "factory" of the activity type (that will defer instantiation) instead of an early-instantiated Activity instance.
 
and I intend to further expand these ActivityFactories to help in
CodeSplitting,
through AsyncProxyProvider.
 
therefore this is the reason I was planning to use one Provider per
Activity, now I am going to use
one Factory per Activity.

but you hinted on GIN assisted inject. could you please elaborate a
little on that ?
and in your opinion is the idea behind using ActivityFactory flawed ?
can you think of an alternative approach or suggest a way to improve
what I'm trying to achieve ?

From your current working code that maps things to activities, *just* replace Map<foo, Activity> with Map<foo, Provider<Activity>>.

Then, look at the code generated by GIN (pass "-gen someFolder" to the GWT compiler or DevMode) to better understand what it does (maybe use a smaller project and iterate adding/changing things and looking at the generated code).

zixzigma

unread,
Jan 9, 2011, 11:34:12 AM1/9/11
to Google Web Toolkit
Thank You very much for your always insightful comments.

On Jan 9, 3:12 am, Thomas Broyer <t.bro...@gmail.com> wrote:
> On Sunday, January 9, 2011 2:28:07 AM UTC+1, zixzigma wrote:

> The whole idea of Provider is that Guice/GIN implement them!
> You only have to "ask" for it and GIN will provide it, e.g.
> @Inject
> MyObject(SomeObject thisWillBeAnInitializedInstance, Provider<SomeObject>
> thisWillBeAProvider) {
> ...
>
> }
>

> If you don't need to pass arguments, then just inject Provider<MyActivity>
> instead of Activity and you have a "factory" of the activity type (that will
> defer instantiation) instead of an early-instantiated Activity instance.
>

"then just inject Provider<MyActivity> instead of Activity and you
have a "factory" of the activity type"
I want to emphasize the "activity TYPE" in your comment:

so in the code below, we have MyActivity1, MyActivity2 ..
MyActivity10, and they are of type MyActivity, right ?

interface MyActivity extends Activity {}
class MyActivity1 implements MyActivity {//..}
class MyActivity2 implements MyActivity {//...}
...
class MyActivity 10 implements MyActivity {//,,,}

now considering this,
> @Inject
> MyObject(SomeObject thisWillBeAnInitializedInstance, Provider<SomeObject>
> thisWillBeAProvider) {

and that the point of Provider being GIN provides them, and there
would be no need for us to implement it,
does it mean that I can just use the code below ?

@Inject
MyObject(SomeObject thisWillBeAnInitializedInstance,
Provider<MyActivity1>
thisWillBeAProvider) {


and it works out of the box ?

or I have to at least define the following Provider ?

public class MyActivityProvider implements Provider<A extends
MyActivity>{

private final A activity;

// ### do we have to use @Inject here ? ###
@Inject
public MyActivityProvider(A actvt){
this.activity = actvt;
}

A get() {
return activity;
}

}

and what is the correct way to configure it ?

bind(MyActivity.class).toProvider(MyActivityProvider.class).

and although I have bound only MyActivity.class to the provider,
it also provides MyActivity1, MyActivity2 and "? extends MyActivity" ?


Thank You

Thomas Broyer

unread,
Jan 9, 2011, 12:25:01 PM1/9/11
to google-we...@googlegroups.com


On Sunday, January 9, 2011 5:34:12 PM UTC+1, zixzigma wrote:
does it mean that I can just use the code below ?

 @Inject
 MyObject(SomeObject thisWillBeAnInitializedInstance,
Provider<MyActivity1>
 thisWillBeAProvider) {


and it works out of the box ?

Yes!

and what is the correct way to configure it ?

Nothing special!

If GIN is able to inject an instance of a given class X, it's able to inject a Provider<X>.

bind(MyActivity.class).toProvider(MyActivityProvider.class).

and although I have bound only MyActivity.class to the provider,
it also provides MyActivity1, MyActivity2 and "? extends MyActivity" ?

No!
 
Reply all
Reply to author
Forward
0 new messages