package com.airbnb.epoxy;
import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.airbnb.epoxy.DataBindingEpoxyModel.DataBindingHolder;
import java.util.List;
/**
* A version of {@link com.airbnb.epoxy.EpoxyModel} that can be used with databinding. The layout
* resource used with this model must be a databinding layout. This class will create the
* databinding object from the layout and call the {@link #setDataBindingVariables} methods when the
* view needs binding to the model.
* <p>
* The easiest way to use this model is to have Epoxy generate a model to do all the binding work
* for you. To do this, create an abstract subclass of this model, annotate it with {@link
* EpoxyModelClass}, and pass your layout resource as the layout param. (You must pass the layout
* this way instead of implementing {@link #getDefaultLayout()}).
* <p>
* Then, make a field to represent each of the data variables in your layout and annotate each one
* with {@link EpoxyAttribute}. The name of each field must match the name of the variable in the
* layout exactly.
* <p>
* Epoxy will generate a subclass of your model at compile time that implements {@link
* #setDataBindingVariables(ViewDataBinding)} and {@link #setDataBindingVariables(ViewDataBinding,
* EpoxyModel)} for you. This will do all binding for you, and also only bind variables that change
* if you update your model (Note: The change optimization only works when used with {@link
* EpoxyController}).
*/
public abstract class DataBindingEpoxyModel extends EpoxyModelWithHolder<DataBindingHolder> {
@Override
View buildView(ViewGroup parent) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
ViewDataBinding binding = DataBindingUtil.inflate(layoutInflater, getViewType(), parent, false);
View view = binding.getRoot();
view.setTag(binding);
return view;
}
@Override
public void bind(DataBindingHolder holder) {
setDataBindingVariables(holder.dataBinding);
holder.dataBinding.executePendingBindings();
}
@Override
public void bind(DataBindingHolder holder, EpoxyModel<?> previouslyBoundModel) {
setDataBindingVariables(holder.dataBinding, previouslyBoundModel);
holder.dataBinding.executePendingBindings();
}
@Override
public void bind(DataBindingHolder holder, List<Object> payloads) {
setDataBindingVariables(holder.dataBinding, payloads);
holder.dataBinding.executePendingBindings();
}
/**
* This is called when the model is bound to a view, and the view's variables should be updated
* with the model's data. {@link ViewDataBinding#executePendingBindings()} is called for you after
* this method is run.
* <p>
* If you leave your class abstract and have a model generated for you via annotations this will
* be implemented for you. However, you may choose to implement this manually if you like.
*/
protected abstract void setDataBindingVariables(ViewDataBinding binding);
/**
* Similar to {@link #setDataBindingVariables(ViewDataBinding)}, but this method only binds
* variables that have changed. The changed model comes from {@link #bind(DataBindingHolder,
* EpoxyModel)}. This will only be called if the model is used in an {@link EpoxyController}
* <p>
* If you leave your class abstract and have a model generated for you via annotations this will
* be implemented for you. However, you may choose to implement this manually if you like.
*/
protected void setDataBindingVariables(ViewDataBinding dataBinding,
EpoxyModel<?> previouslyBoundModel) {
setDataBindingVariables(dataBinding);
}
protected void setDataBindingVariables(ViewDataBinding dataBinding, List<Object> payloads) {
setDataBindingVariables(dataBinding);
}
@Override
public void unbind(DataBindingHolder holder) {
holder.dataBinding.unbind();
}
@Override
protected final DataBindingHolder createNewHolder() {
return new DataBindingHolder();
}
public static class DataBindingHolder extends EpoxyHolder {
private ViewDataBinding dataBinding;
public ViewDataBinding getDataBinding() {
return dataBinding;
}
@Override
protected void bindView(View itemView) {
dataBinding = (ViewDataBinding) itemView.getTag();
}
}
}