package com.airbnb.epoxy;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.util.LongSparseArray;
import java.util.List;
/**
* A helper class for tracking changed models found by the {@link com.airbnb.epoxy.DiffHelper} to
* be included as a payload in the
* {@link android.support.v7.widget.RecyclerView.Adapter#notifyItemChanged(int, Object)}
* call.
*/
public class DiffPayload {
private final EpoxyModel<?> singleModel;
private final LongSparseArray<EpoxyModel<?>> modelsById;
DiffPayload(List<? extends EpoxyModel<?>> models) {
if (models.isEmpty()) {
throw new IllegalStateException("Models must not be empty");
}
int modelCount = models.size();
if (modelCount == 1) {
// Optimize for the common case of only one model changed.
singleModel = models.get(0);
modelsById = null;
} else {
singleModel = null;
modelsById = new LongSparseArray<>(modelCount);
for (EpoxyModel<?> model : models) {
modelsById.put(model.id(), model);
}
}
}
/**
* Looks through the payloads list and returns the first model found with the given model id. This
* assumes that the payloads list will only contain objects of type {@link DiffPayload}, and will
* throw if an unexpected type is found.
*/
@Nullable
public static EpoxyModel<?> getModelFromPayload(List<Object> payloads, long modelId) {
if (payloads.isEmpty()) {
return null;
}
for (Object payload : payloads) {
DiffPayload diffPayload = (DiffPayload) payload;
if (diffPayload.singleModel != null) {
if (diffPayload.singleModel.id() == modelId) {
return diffPayload.singleModel;
}
} else {
EpoxyModel<?> modelForId = diffPayload.modelsById.get(modelId);
if (modelForId != null) {
return modelForId;
}
}
}
return null;
}
@VisibleForTesting
boolean equalsForTesting(DiffPayload that) {
if (singleModel != null) {
return that.singleModel == singleModel;
}
int thisSize = modelsById.size();
int thatSize = that.modelsById.size();
if (thisSize != thatSize) {
return false;
}
for (int i = 0; i < thisSize; i++) {
long thisKey = modelsById.keyAt(i);
long thatKey = that.modelsById.keyAt(i);
if (thisKey != thatKey) {
return false;
}
EpoxyModel<?> thisModel = modelsById.valueAt(i);
EpoxyModel<?> thatModel = that.modelsById.valueAt(i);
if (thisModel != thatModel) {
return false;
}
}
return true;
}
}