package com.airbnb.epoxy;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import java.util.Collections;
import java.util.List;
public final class EpoxyControllerAdapter extends BaseEpoxyAdapter {
private final DiffHelper diffHelper = new DiffHelper(this, true);
private final NotifyBlocker notifyBlocker = new NotifyBlocker();
private final EpoxyController epoxyController;
private List<EpoxyModel<?>> currentModels = Collections.emptyList();
private List<EpoxyModel<?>> copyOfCurrentModels;
private int itemCount;
EpoxyControllerAdapter(EpoxyController epoxyController) {
this.epoxyController = epoxyController;
registerAdapterDataObserver(notifyBlocker);
}
@Override
protected void onExceptionSwallowed(RuntimeException exception) {
epoxyController.onExceptionSwallowed(exception);
}
@Override
List<EpoxyModel<?>> getCurrentModels() {
return currentModels;
}
@Override
public int getItemCount() {
// RecyclerView calls this A LOT. The base class implementation does
// getCurrentModels().size() which adds some overhead because of the method calls.
// We can easily memoize this, which seems to help when there are lots of models.
return itemCount;
}
void setModels(List<EpoxyModel<?>> models) {
itemCount = models.size();
copyOfCurrentModels = null;
this.currentModels = models;
notifyBlocker.allowChanges();
diffHelper.notifyModelChanges();
notifyBlocker.blockChanges();
}
@Override
boolean diffPayloadsEnabled() {
return true;
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
epoxyController.onAttachedToRecyclerViewInternal(recyclerView);
}
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
epoxyController.onDetachedFromRecyclerViewInternal(recyclerView);
}
@Override
public void onViewAttachedToWindow(EpoxyViewHolder holder) {
super.onViewAttachedToWindow(holder);
epoxyController.onViewAttachedToWindow(holder, holder.getModel());
}
@Override
public void onViewDetachedFromWindow(EpoxyViewHolder holder) {
super.onViewDetachedFromWindow(holder);
epoxyController.onViewDetachedFromWindow(holder, holder.getModel());
}
@Override
protected void onModelBound(EpoxyViewHolder holder, EpoxyModel<?> model, int position,
@Nullable EpoxyModel<?> previouslyBoundModel) {
epoxyController.onModelBound(holder, model, position, previouslyBoundModel);
}
@Override
protected void onModelUnbound(EpoxyViewHolder holder, EpoxyModel<?> model) {
epoxyController.onModelUnbound(holder, model);
}
/** Get an unmodifiable copy of the current models set on the adapter. */
public List<EpoxyModel<?>> getCopyOfModels() {
if (copyOfCurrentModels == null) {
copyOfCurrentModels = new UnmodifiableList<>(currentModels);
}
return copyOfCurrentModels;
}
public EpoxyModel<?> getModelAtPosition(int position) {
return currentModels.get(position);
}
/**
* Searches the current model list for the model with the given id. Returns the matching model if
* one is found, otherwise null is returned.
*/
@Nullable
public EpoxyModel<?> getModelById(long id) {
for (EpoxyModel<?> model : currentModels) {
if (model.id() == id) {
return model;
}
}
return null;
}
protected int getModelPosition(EpoxyModel<?> targetModel) {
int size = currentModels.size();
for (int i = 0; i < size; i++) {
EpoxyModel<?> model = currentModels.get(i);
if (model.id() == targetModel.id()) {
return i;
}
}
return -1;
}
}