@Retention(value=RUNTIME) public @interface Prop
Component are its props. The props for a given Component are the union of all
arguments annotated with Prop in your spec methods. The same prop can be defined and
accessed in multiple lifecycle methods. The annotation processor will validate that the props are
being used with the correct type and name.
For each unique prop defined on the spec, the annotation processor adds a setter method on the
Component's Builder that has the same name as the prop. By default props are required but can be
marked as optional(). A prop can also be constrained further by setting it's resType().
The parent component sets the props when it creates the component in it's OnCreateLayout method. The props cannot be updated throughout the lifecycle of the component
unless they are marked as dynamic(). If the layout need to be updated, the parent has to
create a new component and set new props. The props should be immutable since the layout
can be calculated on multiple threads. Immutability of the props ensures that no thread safety
issues can occur in the component hierarchy.
Creating Props:
@LayoutSpec
public class HeaderSpec {
@OnCreateLayout
static Component onCreateLayout(
ComponentContext c,
@Prop MyTitles title,
@Prop(varArg = imageUrl) List<String> urls,
@Prop(optional = true) boolean isSelected) {
if (urls.isEmpty()) {
return null;
}
return Column.create(c)
.paddingDip(YogaEdge.ALL, 8)
.backgroundColor(isSelected ? Color.WHITE : Color.GREEN)
.child(
Image.create(c)
.url(urls.get(0))
.marginDip(YogaEdge.BOTTOM, 4)
)
.child(
Text.create(c)
.text(title.getTitle())
.textSizeSp(16)
.marginDip(YogaEdge.BOTTOM, 4)
)
.child(
Text.create(c)
.text(title.getSubtitle())
.textSizeSp(12)
)
.build();
}
}
Notice how imageUrl, title and isSelected are used to set properties
on different components within the layout.
Setting Props:
@LayoutSpec
public class MyComponent {
@OnCreateLayout
static Component onCreateLayout(ComponentContext c) {
return Header.create(c)
.title(new MyTitles("title", "subtitle"))
.imageUrl("https://example.com/image.jpg")
.build();
}
}ResType,
PropDefault,
OnCreateLayout,
State,
Param| Modifier and Type | Optional Element and Description |
|---|---|
String |
docString |
boolean |
dynamic
EXPERIMENTAL.
|
boolean |
isCommonProp |
boolean |
optional
Declares that this prop can be omitted by the caller of the component.
|
boolean |
overrideCommonPropBehavior
This may only be set to true if
isCommonProp() is also set to true. |
ResType |
resType
Marks this prop as one that corresponds to a specific Android resource type, and therefore
generates various helper methods to initialize it.
|
String |
varArg
Declares this prop supports a variable arguments, and provide utility methods to add values to
the prop.
|
public abstract boolean optional
PropDefault and has the same name and type as the prop.true iff the prop is optional otherwise false.public abstract ResType resType
For example, a CharSequence prop named "title" may be marked as ResType.STRING. This will make the component have not only method "title(CharSequence)" but
also various methods that enable initializing the prop from a resource or attribute:
titleRes(@StringRes int resId)
titleRes(@StringRes int resId, Object... formatArgs)
titleAttr(@AttrRes int attrResId, @StringRes int defResId)
titleAttr(@AttrRes int attrResId)
public abstract String docString
public abstract String varArg
For example, having @Prop(varArg="name") List<CharSequence> names would generate a
setter name method which can be called multiple times to add a set of names.
The prop must be a parameterized list. It is effectively always optional(), and has
an empty list (immutable) as a default value.
MyComponent.create(c)
.name("A")
.name("B")
.name("C")
public abstract boolean isCommonProp
true if the name of the prop conflicts with a common prop.public abstract boolean overrideCommonPropBehavior
isCommonProp() is also set to true. If true, then the behavior of it's common props will be overridden. If false, then the
common prop will applied by the framework level as normal as well as any behavior that the
component declares within the spec.true if the framework should not apply the common prop.public abstract boolean dynamic
Marks a Prop as dynamic, so that a DynamicValue object could be passed to a
Component that the Prop belongs to, which makes it possible to update the actual value
of the Prop bypassing LayoutState and MountState.
Only Props that DO NOT AFFECT LAYOUT could be marked as dynamic.
Additionally, for every dynamic Prop, a ComponentSpec must contain OnBindDynamicValue method, that applies the actual value to the mounted content.
OnBindDynamicValue