Let's take some distance with your questions and answer the overall concern at once. But first, my favorite catchphrase:
There's no magic!
UiBinder is a tool that takes an XML definition and generates Java code out of it. That is to say (and that's true for everything constructed through a call to GWT.create()
: there's no magic!) that you could have written the same by hand, in Java code. In other words, UiBinder is only a tool to get you more productive, by requiring less code to achieve the same goal. But as it generates code that you could have written by hand, it won't give better performance at runtime (not worse either); it however makes it easier to use patterns that result in better performance, namely HTMLPanel
: maintaining HTMLPanel
-based code in pure-Java is a nightmare, and the complete opposite with UiBinder.
UiBinder will:
- generate an implicit
ClientBundle
, with an implicit CssResource
for each <ui:style>
, implicit an ImageResource
for each <ui:image>
and an implicit DataResource
for each <ui:data>
- generate an implicit
Messages
interface for I18N out of <ui:msg>
, <ui:ph>
et al.
- inject objects into fields of a partner object (known as the owner and passed as argument to the
createAndBindUi
method) based on ui:field
attributes in the XML and @UiField
annotations in the Java code; or possibly retrieve them from the partner object instead, if the annotation has provided=true
- create objects using various specialized parsers, or
@UiConstructor
-annotated constructors, or @UiFactory
-annotated methods of the partner object, or as a last resort using a GWT.create()
call
- bind
@UiHandler
-annotated methods of the partner object as event handlers for widgets in the XML template (based on the ui:field
attributes)
- and last but not least: assemble all those constructed objects together, and set some of their properties (out of attributes in the XML).
The most common use of UiBinder is for those objects I talked about above to be widgets. Assembling them then means adding widgets into other container widgets.
This is why you generally see UiBinder being used inside a Composite
to provide the value for the initWidget()
method: UiBinder will create and put together all the widgets needed and return the top-most one, to be used as the root for the composite widget.
You'll have understood already: you won't use UiBinder over widgets, and widgets aren't translated to UiBinder XML (quite the contrary actually).
Now to your more specific questions:
Do you write lots of UIBinder XML "snippets" or just pack them all into one big monolithic XML file?
UiBinder is kind of an implementation detail. Most of the time, you'll build (reusable) widgets (composites) with UiBinder; it won't transpire to the outside world, which will only see a widget, not "something built with UiBinder".
That means you'll have lots of small/medium UiBinder templates (generally one per screen in your app, at the very least, or for a more general rule, one per complex UI component).
For making my own custom components, what's the difference between extending com.google.gwt.user.client.ui.* vs. com.google.gwt.user.client.ui.Composite?
Ümit answered that one, and the documentation too: https://developers.google.com/web-toolkit/doc/latest/DevGuideUiCustomWidgets
Division of labor: Widgets/UIBinder vs. Layouts vs CSS files: who does what?
There's unfortunately no simple answer to that one. It depends.
It depends the kind of application you're building, and the kind of UI you want. For the "global layout" of your app, you'll use either several RootPanel
or one big HTMLPanel
and do the layout with HTML and CSS (either in the HTML host page, or in a UiBinder template to serve as a shell for your app), or you'll use so-called layout panels.
For more localized layout (inside composite widgets), I'd recommend using HTMLPanel
or FlowPanel
; or possibly layout panels. If you need to handle scroll events, or if you need scrolling right inside a container widget, then use a ScrollPanel
, otherwise just use overflow: scroll
in CSS.
There are tradeoffs. You'll have to do experiments. And in the end, use what you think is good for you. There's no one-size-fits-all.
Finally, while it's its most common use case, note that UiBinder can be used without widgets, for example to create non-composite widgets (or UiObject
s, but there's very few use cases for them; you'll see them used for MenuItem
s and TreeItem
s for instance), using setElement()
rather than initWidget()
, or create custom Cells.
And actually, there isn't much use cases for Composite
either: you can simply implement IsWidget
(returning the result of createAndBindUi
, called once and cached in a private field) and it should work everywhere a widget is expected/accepted.