package com.lin.poweradapter;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.SparseArrayCompat;
import android.view.ViewGroup;
import java.util.Collections;
import java.util.List;
public class AdapterDelegatesManager<T, VH extends PowerViewHolder> {
static final int FALLBACK_DELEGATE_VIEW_TYPE = Integer.MAX_VALUE - 1;
private static final List<Object> PAYLOADS_EMPTY_LIST = Collections.emptyList();
protected SparseArrayCompat<AdapterDelegate<T, VH>> delegates = new SparseArrayCompat();
protected AdapterDelegate<Object, PowerViewHolder> fallbackDelegate;
public AdapterDelegatesManager<T, VH> addDelegate(@NonNull AdapterDelegate<T, VH> delegate) {
// algorithm could be improved since there could be holes,
// but it's very unlikely that we reach Integer.MAX_VALUE and run out of unused indexes
int viewType = delegates.size();
while (delegates.get(viewType) != null) {
viewType++;
if (viewType == FALLBACK_DELEGATE_VIEW_TYPE) {
throw new IllegalArgumentException(
"Oops, we are very close to Integer.MAX_VALUE. It seems that there are no more free and unused view type integers left to add another AdapterDelegate.");
}
}
return addDelegate(viewType, false, delegate);
}
public AdapterDelegatesManager<T, VH> addDelegate(int viewType,
@NonNull AdapterDelegate<T, VH> delegate) {
return addDelegate(viewType, false, delegate);
}
public AdapterDelegatesManager<T, VH> addDelegate(int viewType, boolean allowReplacingDelegate,
@NonNull AdapterDelegate<T, VH> delegate) {
if (delegate == null) {
throw new NullPointerException("AdapterDelegate is null!");
}
if (viewType == FALLBACK_DELEGATE_VIEW_TYPE) {
throw new IllegalArgumentException("The view type = "
+ FALLBACK_DELEGATE_VIEW_TYPE
+ " is reserved for fallback adapter delegate (see setFallbackDelegate() ). Please use another view type.");
}
if (!allowReplacingDelegate && delegates.get(viewType) != null) {
throw new IllegalArgumentException(
"An AdapterDelegate is already registered for the viewType = "
+ viewType
+ ". Already registered AdapterDelegate is "
+ delegates.get(viewType));
}
delegates.put(viewType, delegate);
return this;
}
public AdapterDelegatesManager<T, VH> removeDelegate(@NonNull AdapterDelegate<T, VH> delegate) {
if (delegate == null) {
throw new NullPointerException("AdapterDelegate is null");
}
int indexToRemove = delegates.indexOfValue(delegate);
if (indexToRemove >= 0) {
delegates.removeAt(indexToRemove);
}
return this;
}
public AdapterDelegatesManager<T, VH> removeDelegate(int viewType) {
delegates.remove(viewType);
return this;
}
public int getItemViewType(@NonNull T items, int position) {
if (items == null) {
throw new NullPointerException("Items datasource is null!");
}
int delegatesCount = delegates.size();
for (int i = 0; i < delegatesCount; i++) {
AdapterDelegate<T, VH> delegate = delegates.valueAt(i);
if (delegate.isForViewType(items, position)) {
return delegates.keyAt(i);
}
}
if (fallbackDelegate != null) {
return FALLBACK_DELEGATE_VIEW_TYPE;
}
throw new NullPointerException(
"No AdapterDelegate added that matches position=" + position + " in data source");
}
@NonNull
public VH onCreateViewHolder(ViewGroup parent, int viewType) {
AdapterDelegate<T, VH> delegate = getDelegateForViewType(viewType);
if (delegate == null) {
throw new NullPointerException("No AdapterDelegate added for ViewType " + viewType);
}
VH vh = delegate.onCreateViewHolder(parent);
if (vh == null) {
throw new NullPointerException("ViewHolder returned from AdapterDelegate "
+ delegate
+ " for ViewType ="
+ viewType
+ " is null!");
}
return vh;
}
public void onBindViewHolder(@NonNull T items, int position,
@NonNull VH viewHolder, List payloads) {
AdapterDelegate<T, VH> delegate = getDelegateForViewType(viewHolder.getItemViewType());
if (delegate == null) {
throw new NullPointerException("No delegate found for item at position = "
+ position
+ " for viewType = "
+ viewHolder.getItemViewType());
}
delegate.onBindViewHolder(items, position, viewHolder,
payloads != null ? payloads : PAYLOADS_EMPTY_LIST);
}
public void onBindViewHolder(@NonNull T items, int position,
@NonNull VH viewHolder) {
onBindViewHolder(items, position, viewHolder, PAYLOADS_EMPTY_LIST);
}
public void onViewRecycled(@NonNull VH viewHolder) {
AdapterDelegate<T, VH> delegate = getDelegateForViewType(viewHolder.getItemViewType());
if (delegate == null) {
throw new NullPointerException("No delegate found for "
+ viewHolder
+ " for item at position = "
+ viewHolder.getAdapterPosition()
+ " for viewType = "
+ viewHolder.getItemViewType());
}
delegate.onViewRecycled(viewHolder);
}
public boolean onFailedToRecycleView(@NonNull VH viewHolder) {
AdapterDelegate<T, VH> delegate = getDelegateForViewType(viewHolder.getItemViewType());
if (delegate == null) {
throw new NullPointerException("No delegate found for "
+ viewHolder
+ " for item at position = "
+ viewHolder.getAdapterPosition()
+ " for viewType = "
+ viewHolder.getItemViewType());
}
return delegate.onFailedToRecycleView(viewHolder);
}
public void onViewAttachedToWindow(VH viewHolder) {
AdapterDelegate<T, VH> delegate = getDelegateForViewType(viewHolder.getItemViewType());
if (delegate == null) {
throw new NullPointerException("No delegate found for "
+ viewHolder
+ " for item at position = "
+ viewHolder.getAdapterPosition()
+ " for viewType = "
+ viewHolder.getItemViewType());
}
delegate.onViewAttachedToWindow(viewHolder);
}
public void onViewDetachedFromWindow(VH viewHolder) {
AdapterDelegate<T, VH> delegate = getDelegateForViewType(viewHolder.getItemViewType());
if (delegate == null) {
throw new NullPointerException("No delegate found for "
+ viewHolder
+ " for item at position = "
+ viewHolder.getAdapterPosition()
+ " for viewType = "
+ viewHolder.getItemViewType());
}
delegate.onViewDetachedFromWindow(viewHolder);
}
public void setFallbackDelegate(
@Nullable AdapterDelegate<Object, PowerViewHolder> fallbackDelegate) {
this.fallbackDelegate = fallbackDelegate;
}
public int getViewType(@NonNull AdapterDelegate<T, VH> delegate) {
if (delegate == null) {
throw new NullPointerException("Delegate is null");
}
int index = delegates.indexOfValue(delegate);
if (index == -1) {
return -1;
}
return delegates.keyAt(index);
}
@Nullable
public AdapterDelegate<T, VH> getDelegateForViewType(int viewType) {
AdapterDelegate<T, VH> delegate = delegates.get(viewType);
if (delegate == null) {
if (fallbackDelegate == null) {
return null;
} else {
return (AdapterDelegate<T, VH>) fallbackDelegate;
}
}
return delegate;
}
public AdapterDelegate<T, VH> getDelegateForViewType(@NonNull T items, int position) {
if (items == null) {
throw new NullPointerException("Items datasource is null!");
}
int delegatesCount = delegates.size();
for (int i = 0; i < delegatesCount; i++) {
AdapterDelegate<T, VH> delegate = delegates.valueAt(i);
if (delegate.isForViewType(items, position)) {
return delegate;
}
}
return null;
}
@Nullable
public AdapterDelegate<Object, PowerViewHolder> getFallbackDelegate() {
return fallbackDelegate;
}
}