package io.jiantao.android.uikit.adapter.loadmore; import android.support.annotation.IntDef; import android.support.annotation.NonNull; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Collections; import java.util.List; import me.drakeet.multitype.ItemViewBinder; import me.drakeet.multitype.Items; import me.drakeet.multitype.MultiTypeAdapter; import me.drakeet.multitype.MultiTypePool; import me.drakeet.multitype.TypePool; /** * 分页加载Adapter * * @author jiantao */ public class MultiTypeLoadMoreAdapter extends MultiTypeAdapter implements LoadMoreDelegate.LoadMoreSubject { private static final String TAG = MultiTypeLoadMoreAdapter.class.getSimpleName(); private AbstractItemViewBinder loadMoreItemViewBinder; final LoadMoreItem loadMoreItem; final LoadMoreDelegate loadMoreDelegate; private LoadMoreDelegate.LoadMoreSubject loadMoreSubject; public MultiTypeLoadMoreAdapter() { this(Collections.emptyList()); } public MultiTypeLoadMoreAdapter(@NonNull List<?> items) { this(items, 16); } public MultiTypeLoadMoreAdapter(@NonNull List<?> items, int initialCapacity) { this(items, new MultiTypePool(initialCapacity)); } public MultiTypeLoadMoreAdapter(@NonNull List<?> items, @NonNull TypePool pool) { super(items, pool); loadMoreItem = new LoadMoreItem(); loadMoreDelegate = new LoadMoreDelegate(this); loadMoreItemViewBinder = new DefaultLoadMoreItemViewBinder(); register(LoadMoreItem.class, loadMoreItemViewBinder); } @Override public void setItems(@NonNull List<?> items) { if (items.isEmpty()) { // empty call super super.setItems(items); return; } Items tempItems = new Items(items.size() + 1); //插在loadmore之前 tempItems.addAll(items); tempItems.add(loadMoreItem); super.setItems(tempItems); } public void setLoadMoreItemState(@LoadMoreItem.ItemState int state) { this.loadMoreItem.setState(state); notifyItemChanged(getItemCount() - 1); } /** * @param listener retry event callback */ public void setLoadMoreRetryListener(ILoadMoreRetryListener listener) { loadMoreItemViewBinder.setLoadMoreRetryListener(listener); } public void setLoadMoreItemViewBinder(@NonNull AbstractItemViewBinder viewBinder) { viewBinder.setLoadMoreRetryListener(loadMoreItemViewBinder.mListener); this.loadMoreItemViewBinder = viewBinder; register(LoadMoreItem.class, viewBinder); } @Override public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) { loadMoreDelegate.attach(recyclerView); final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager == null) { Log.e(TAG, "Cannot setSpanSizeLookup on a null LayoutManager Object. " + "Call setLayoutManager with a non-null argument."); return; } if (layoutManager instanceof GridLayoutManager) { ((GridLayoutManager) layoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { Object obj = getItems().get(position); return obj.getClass().equals(LoadMoreItem.class) ? ((GridLayoutManager) layoutManager).getSpanCount() : 1; } }); } } public void setLoadMoreSubject(LoadMoreDelegate.LoadMoreSubject loadMoreSubject) { this.loadMoreSubject = loadMoreSubject; } @Override public boolean isLoading() { return loadMoreSubject == null || loadMoreSubject.isLoading(); } @Override public void onLoadMore() { if (loadMoreSubject != null && loadMoreItem.getState() == LoadMoreItem.STATE_LOADING) { loadMoreSubject.onLoadMore(); } } /** * dataEntity for LoadMoreViewBinder */ public static class LoadMoreItem { public static final int STATE_LOADING = 0; /** * finish load */ public static final int STATE_NO_MORE_DATA = 1; public static final int STATE_FAILED = 2; /** * not visible */ public static final int STATE_GONE = 3; @Retention(RetentionPolicy.SOURCE) @IntDef({STATE_NO_MORE_DATA, STATE_FAILED, STATE_LOADING, STATE_GONE}) public @interface ItemState { } private int mState = STATE_LOADING; @ItemState public int getState() { return mState; } public void setState(@ItemState int mState) { this.mState = mState; } } static class DefaultLoadMoreItemViewBinder extends AbstractItemViewBinder<DefaultLoadMoreItemViewBinder.DefaultViewHolder> { @Override protected DefaultViewHolder createViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { TextView view = new TextView(inflater.getContext()); RecyclerView.LayoutParams params = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); view.setLayoutParams(params); view.setGravity(Gravity.CENTER); return new DefaultViewHolder(view); } class DefaultViewHolder extends ViewHolder { public DefaultViewHolder(@NonNull View itemView) { super(itemView); } @Override public void setState(int state) { String tips = "state_none"; switch (state) { case LoadMoreItem.STATE_LOADING: tips = "state loading"; break; case LoadMoreItem.STATE_FAILED: tips = "state failed"; break; case LoadMoreItem.STATE_NO_MORE_DATA: tips = "state no more data"; break; case LoadMoreItem.STATE_GONE: itemView.setVisibility(View.GONE); break; default: break; } ((TextView) itemView).setText(tips); } } } /** * loadMoreViewBinder基类,限制子类实现各种状态。 */ public static abstract class AbstractItemViewBinder<VH extends ViewHolder> extends ItemViewBinder<LoadMoreItem, VH> { private ILoadMoreRetryListener mListener; @NonNull @Override protected final VH onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { VH viewHolder = createViewHolder(inflater, parent); viewHolder.mListener = mListener; return viewHolder; } @Override protected final void onBindViewHolder(@NonNull VH holder, @NonNull LoadMoreItem item) { holder.data = item; holder.setState(item.getState()); } protected abstract VH createViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent); void setLoadMoreRetryListener(ILoadMoreRetryListener listener) { this.mListener = listener; } } /** * loadMore ViewHolder 基类 */ public static abstract class ViewHolder extends RecyclerView.ViewHolder { protected LoadMoreItem data; ILoadMoreRetryListener mListener; public ViewHolder(@NonNull View itemView) { super(itemView); itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mListener != null && data != null && data.getState() == LoadMoreItem.STATE_FAILED) { mListener.retry(); data.mState = LoadMoreItem.STATE_LOADING; setState(data.mState); } } }); } public abstract void setState(@LoadMoreItem.ItemState int state); } public interface ILoadMoreRetryListener { /** * try again */ void retry(); } }