Thanks for taking the time to right this up. It's really appreciated.

On Wed, Jul 21, 2010 at 6:13 PM, Thomas Broyer <[email protected]> wrote:

> Hi G-Men,
>
> I've started prototyping with Activities and can now give some more
> feedback on how it compares to my previous own implementation of a
> PlaceManager and how I used it with MVP.
>
> First, my PlaceManager was nothing more than the PlaceController found
> in GWT 2.1. This meant that when handling PlaceChangeEvents, I
> instantiated a new presenter and showed its view right away. The view
> generally displayed a "loading..." label while the presenter sent a
> request to the server to retrieve the data and only then ask the view
> to hide the "loading..." and display the loaded data.
>
> It always floated around in my head that it'd be better to first load
> the data and only then switch the views; which happens to be what
> GMail does (seems to do), for instance. It makes error handling easier
> because when there's an error loading the data (such as when you
> temporarily lose your network (wifi?) connection) you're not stuck
> with a "loading..." label but still are in front of the same "screen",
> where you can click again to retry, or even click elsewhere to finally
> do something else. Cancelling XHRs (hitting the Esc key in Firefox
> aborts XHRs too, which is highly more probable than a loss of
> connectivity) can also be the cause of such behaviors.
>
> When I saw how Activity offers to handle this (async start), I was
> really pleased.
>
> Thinking a bit more about it, there's still some to be done, IMO.
>
> 1. in ActivityManager, the current activity is first stopped, then the
> next activity replaces it and is started asynchronously. This means
> that if the next activity (new current one) fails to load, the
> activity corresponding to the displayed view is no longer known,
> already stopped, and could even have been garbage collected! IMO, the
> current activity should only be stopped and "forgotten" when the new
> one is fully started (i.e. calls the Display back with a view to
> display), no sooner.
> It should be as easy as replacing the startingNext boolean with the
> reference to the next activity in the ActivityManager, and switching
> the current activity for the next one from within the
> ProtectedDisplay.
>

I don't think I agree with this. I think the odds are that you're leaving an
activity that thinks it's done now, and may be hard pressed to respond
reasonably to events.

>
> 2. The <P extends Place> type parameter should be better documented.
> As I understand it from reading the code, this is intended so you can
> use an application-specific Place subclass as the base class for all
> your Places and it then saves you the cast from Place to
> BaseMyAppPlace (or ScaffoldPlace in the scaffold app). Specifically,
> it is not intended, as you could think at first sight, to "only see" a
> subset of places you're interested in (say you have an activity that
> only maps places extending BaseRecordPlace, you shouldn't use an
> ActvityManager<BaseRecordPlace> as there's no guarantee you'll only be
> passed BaseRecordPlace instances (this is partly because of how Java
> generics are implemented, so any experienced Java developper should
> get it right). Removing the generics wouldn't hurt that much and would
> prevent confusions in what the type parameter means.
>

Agreed, this is a disaster right now. I'm trying to redesign it right now.
I'm
definitely not married to the generics.

>
> 3. As implemented now, an Activity can call the Display back several
> times. I've found a use case for that but I'd like to know if it's
> intended or not (and whichever the outcome, it should probably be
> documented). My use case: we have a "dashboard like" interface, with
> regions similar to "gadgets". For better UX (performance experience),
> we'd like to first display the view with "loading..." placeholders and
> asynchronously load the data to show in each region. I thought about
> implementing each "gadget" as an Activity, managed by the parent
> Activity directly rather than an ActivityManager; i.e. the
> DashboardActivity, in its start(), starts each sub-activity, each with
> a Display corresponding to a region on the screen, and displays itself
> right away. To handle loading errors, the idea is that each sub-
> activity displays an "error view" with a "retry" link; when the user
> clicks "retry", the request is retried and if successful the Display's
> showActivityWidget is called again, this time with the "real" view.
> Would this be a "supported use case"? If not, given that it's not
> using an ActivityManager, I could always make it work, but then it
> would mean the subactivities know that they are subactivities with a
> slightly different Display contract than other activities (which means
> we'd probably use other interfaces than Activity and Display to avoid
> confusions).
>

I don't see anything wrong with "redundant" calls to showActivityWidget,
and I think I was careful to make sure it wouldn't break anything.

To the more general question, I've been trying to stay away from
making Activities nest. Sounds like you're not necessarily asking
for that support?


> 4. plumbing with History could only be a matter of calling
> PlaceController.goTo on History ValueChange, and calling
> History.newItem(token, false) on each PlaceChangeEvent; with some
> PlaceMapper or HistoryMapper to map history tokens to places (in my
> implementation, I called it HistoryMapper, I also made it a dependency
> of the PlaceManager but now think it should just be another component
> listener to those events on the event bus). But I'd like things to
> happen a bit differently for an even better user experience: similarly
> to how I think the current activity should only be stopped when the
> new one is fully started, I think the history token should only change
> at the time too. This is tricky however because there can be more than
> one ActivityManager in an app (or should there be a single one?).
>

I want to allow multiple. I'm trying to figure out now how to get them all
to share the single history token.


> Maybe there should be a "main activity manager" that'd set the history
> when its activity is fully loaded? or maybe there should be a third
> event to wait for all activities to be fully started (this was my
> initial idea in my own implementation, but I don't have a concept of
> activity with async start), and event on which ActivityManager (and
> anyone interested) would "register", incrementing a counter, and call
> back when data is ready, decrementing the counter, the
> PlaceChangeEvent only being fired when the counter reaches 0, with the
> effect of calling History.newItem and actually showing the views (just
> in case there's another PlaceChange requested while data was being
> loaded, which currently calls onCancel on the "next" activity).
> This is a just an idea though, it wouldn't work when navigating using
> the browser's history, so maybe (probably?) it's not worth the
> complexity.
>
>  5. Finally, and this is more a "support question" than feedback, we
> have "contextual" widgets, depending on the current activity. Think of
> it as the contextual Ribbon tabs in MS Office 2007: when you're within
> a table, table-specific tabs appear in the "global" Ribbon. We also
> display a breadcrumb (several levels deep) and some kind of
> "breadcrumb overview" on the right, a bit similar to how GMail
> displays contextual widgets on the right of conversations, such as
> when the displayed conversation contains an appointment, to easily add
> it to your calendar. The idea was to create interfaces inheriting
> IsWidget, such as HasRibbonTabs and HasBreadcrumbOverview; and on the
> Display implementation, display the IsWidget#asWidget in the main
> screen "region", then if the IsWidget is an instance of HasRibbonTabs
> show other Widgets retrieved from the HasRibbonTabs interface API in
> the Ribbon, same thing if the IsWidget is an instance of
> HasBreadcrumbOverview. That way, the "activity's main view" can
> directly listen on events of the Ribbon tabs' buttons to callback the
> activity's Delegate, just as if they were directly on the view. The
> alternative would be that each region has an ActivityManager, with
> ActivityMappers doing the exact same tests ("are we in this context?")
> just to call different factories ("return the appropriate Ribbon
> activity" vs. "return the appropriate main activity" vs. "return the
> appropriate breadcrumb overview activity"), each activity making
> similar requests to get the data (with RequestFactory, they should be
> batched and cached so it wouldn't be a bug deal, except in the number
> of times we'd have to code the calls to RequestFactory). What do you
> think?
>

The latter is how I've approached this before. Like you say, the intention
with RequestFactory is that will provide enough caching and batching
smarts that truly redundant requests from isolated sections of
your application won't impose a penalty. AdWords has had a lot
of success with this approach.

-- 
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to