@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 |
---|---|
java.lang.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.
|
java.lang.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 java.lang.String docString
public abstract java.lang.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