-
Notifications
You must be signed in to change notification settings - Fork 727
ViewHolder Models
If you aren't using databinding or custom views you can create an EpoxyModel for a layout using a view holder.
Create a class that extends EpoxyModelWithHolder
. Your model class should be typed with your view holder type.
The view holder class must extend EpoxyHolder
; it can be defined anywhere, but a good pattern is to make it a nested class of the model.
@EpoxyModelClass(layout = R.layout.model_button)
public abstract class ButtonModel extends EpoxyModelWithHolder<Holder> {
// Declare your model properties like this
@EpoxyAttribute @StringRes int text;
@EpoxyAttribute(DoNotHash) OnClickListener clickListener;
@Override
public void bind(Holder holder) {
// Implement this to bind the properties to the view
holder.button.setText(text);
holder.button.setOnClickListener(clickListener);
}
static class Holder extends EpoxyHolder {
Button button;
@Override
protected void bindView(View itemView) {
button = itemView.findViewById(R.id.button);
}
}
}
Upon building the project a ButtonModel_
class will be generated that you can then use in your EpoxyControllers.
The generated model should be instantiated directly, and has a setter for each property:
new ButtonModel_()
.id(1)
.text(R.string.my_text)
.clickListener(() -> // do something);
Some things to note:
-
@EpoxyModelClass(layout = R.layout.model_button)
defines the layout that will be inflated. - Make your model class is abstract. It should not be used directly - instead, the
ButtonModel_
generated class should be instantiated and used in your EpoxyController. - Model properties are defined by annotating fields with
@EpoxyAttribute
. Setters on the generated class will set these fields for us. You should never set these fields directly. - The
bind
method is called when the model is bound to a view, and should be used to set your data on the views in the view holder. - The ViewHolder class simply holds a reference to the views.
bindView
is called once, when the view is inflated.
A useful pattern is to create a base class that all view holders in your app can extend. Your base class can use ButterKnife to bind its view so that subclasses don't explicitly need to.
For example your base class may look like this:
public abstract class BaseEpoxyHolder extends EpoxyHolder {
@CallSuper
@Override
protected void bindView(View itemView) {
ButterKnife.bind(this, itemView);
}
}
Applying this pattern helps shorten our example model to this:
@EpoxyModelClass(layout = R.layout.model_button)
public abstract class ButtonModel extends EpoxyModelWithHolder<Holder> {
@EpoxyAttribute @StringRes int text;
@EpoxyAttribute OnClickListener clickListener;
@Override
public void bind(Holder holder) {
holder.button.setText(text);
holder.button.setOnClickListener(clickListener);
}
static class Holder extends BaseEpoxyHolder {
@BindView(R.id.button) Button button;
}
}
There are Kotlin specific viewholder patterns provided in the Kotlin section of the wiki