BaseMultiItemAdapter

142 阅读2分钟
package com.alibaba.genie.panel.basic.base.adapter;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.ViewGroup;

import com.alibaba.genie.panel.basic.R;

import java.lang.ref.WeakReference;
import java.util.List;

public class BaseMultiItemAdapter<T extends Object> extends BaseQuickAdapter<T, RecyclerView.ViewHolder> {
    private SparseArray<OnMultiItemAdapterListener<T, RecyclerView.ViewHolder>> typeViewHolders =
            new SparseArray<>(1);

    private OnItemViewTypeListener<T> onItemViewTypeListener;

    public BaseMultiItemAdapter() {
        super();
    }

    public BaseMultiItemAdapter(List<T> items) {
        super(items);
    }

    @NonNull
    @Override
    protected RecyclerView.ViewHolder onCreateViewHolder(@NonNull Context context, @NonNull ViewGroup parent, int viewType) {
        OnMultiItemAdapterListener<T, RecyclerView.ViewHolder> listener = typeViewHolders.get(viewType);
        if (listener == null) {
            throw new IllegalArgumentException(String.format("ViewType: %d not found onViewHolderListener,please use addItemType() first!",
                    viewType));
        }
        RecyclerView.ViewHolder holder = listener.onCreate(parent.getContext(), parent, viewType);
        holder.itemView.setTag(R.id.BaseQuickAdapter_key_multi, listener);
        return holder;
    }

    @Override
    protected void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder,
                                    int position,
                                    @Nullable T item) {
        OnMultiItemAdapterListener<T, RecyclerView.ViewHolder> listener = findListener(holder);
        if (listener != null) {
            listener.onBind(holder, position, item);
        }
    }

    @Override
    protected void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder,
                                    int position,
                                    @Nullable T item,
                                    @NonNull List payloads) {
        if (payloads != null || payloads.isEmpty()) {
            onBindViewHolder(holder, position, item);
            return;
        }
        OnMultiItemAdapterListener<T, RecyclerView.ViewHolder> listener = findListener(holder);
        if (listener != null) {
            listener.onBind(holder, position, item, payloads);
        }
    }

    /**
     * Call this function to add multiTypeItems.
     * 调用此方法,设置多布局
     *
     * @param itemViewType Int
     * @param listener     Int
     * @return
     */
    public <V extends RecyclerView.ViewHolder> BaseMultiItemAdapter<T> addItemType(
            int itemViewType, OnMultiItemAdapterListener<T, V> listener) {
        if (listener instanceof OnMultiItem) {
            ((OnMultiItem<T, V>) listener).setWeakA(new WeakReference<>(this));
        }
        typeViewHolders.put(
                itemViewType, (OnMultiItemAdapterListener<T, RecyclerView.ViewHolder>) listener);
        return this;
    }

    /**
     * 设置 ItemViewType 的监听,根据不同数据类型,返回不同的type值
     *
     * @param listener
     */
    public BaseMultiItemAdapter<T> onItemViewType(OnItemViewTypeListener<T> listener) {
        this.onItemViewTypeListener = listener;
        return this;
    }

    @Override
    protected int getItemViewType(int position, @NonNull List<T> list) {
        if (onItemViewTypeListener != null) {
            return onItemViewTypeListener.onItemViewType(position, list);
        } else {
            return super.getItemViewType(position, list);
        }
    }

    @Override
    public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        OnMultiItemAdapterListener<T, RecyclerView.ViewHolder> listener = findListener(holder);
        if (listener != null) {
            listener.onViewAttachedToWindow(holder);
        }
    }

    @Override
    public void onViewDetachedFromWindow(@NonNull RecyclerView.ViewHolder holder) {
        super.onViewDetachedFromWindow(holder);
        OnMultiItemAdapterListener<T, RecyclerView.ViewHolder> listener = findListener(holder);
        if (listener != null) {
            listener.onViewDetachedFromWindow(holder);
        }
    }

    @Override
    public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
        super.onViewRecycled(holder);
        OnMultiItemAdapterListener<T, RecyclerView.ViewHolder> listener = findListener(holder);
        if (listener != null) {
            listener.onViewRecycled(holder);
        }
    }

    @Override
    public boolean onFailedToRecycleView(@NonNull RecyclerView.ViewHolder holder) {
        OnMultiItemAdapterListener<T, RecyclerView.ViewHolder> listener = findListener(holder);
        if (listener != null) {
            return listener.onFailedToRecycleView(holder);
        }
        return super.onFailedToRecycleView(holder);
    }

    @Override
    public boolean isFullSpanItem(int itemType) {
        OnMultiItemAdapterListener<T, RecyclerView.ViewHolder> listener = typeViewHolders.get(itemType);
        if (!super.isFullSpanItem(itemType)) {
            if (listener != null) {
                return listener.isFullSpanItem(itemType);
            } else {
                return false;
            }
        }
        return true;
    }


    private OnMultiItemAdapterListener<T, RecyclerView.ViewHolder> findListener(RecyclerView.ViewHolder holder) {
        Object tag = holder.itemView.getTag(R.id.BaseQuickAdapter_key_multi);
        if (tag instanceof BaseMultiItemAdapter.OnMultiItemAdapterListener) {
            return (OnMultiItemAdapterListener<T, RecyclerView.ViewHolder>) tag;
        }
        return null;
    }

    /**
     * 多类型布局 Adapter Listener
     *
     * @param T 数据类型
     * @param V ViewHolder 类型
     */
    public interface OnMultiItemAdapterListener<T, V extends RecyclerView.ViewHolder> {
        V onCreate(@NonNull Context context, @NonNull ViewGroup parent, int viewType);

        void onBind(@NonNull V holder, int position, @NonNull T item);

        //        void onBind(V holder, int position, T item, List<Object> payloads) {
//            onBind(holder, position, item);
//        }
        void onBind(@NonNull V holder, int position, @NonNull T item, List<Object> payloads);

        void onViewAttachedToWindow(RecyclerView.ViewHolder holder);

        void onViewDetachedFromWindow(RecyclerView.ViewHolder holder);

        void onViewRecycled(RecyclerView.ViewHolder holder);

        boolean onFailedToRecycleView(RecyclerView.ViewHolder holder);

        boolean isFullSpanItem(int itemType);
    }

    /**
     * OnMultiItemAdapterListener 的简单处理
     */
    public static abstract class SimpleOnMultiItemAdapterListener<T, V extends RecyclerView.ViewHolder> implements OnMultiItemAdapterListener<T, V> {

        @Override
        public void onBind(@NonNull V holder, int position, T item, List<Object> payloads) {
            onBind(holder, position, item);
        }

        @Override
        public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {

        }

        @Override
        public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) {

        }

        @Override
        public void onViewRecycled(RecyclerView.ViewHolder holder) {

        }

        @Override
        public boolean onFailedToRecycleView(RecyclerView.ViewHolder holder) {
            return false;
        }

        @Override
        public boolean isFullSpanItem(int itemType) {
            return false;
        }
    }

    /**
     * 如果需要一些属性,例如:adapter、context,则使用此抽象类.
     * 如果不需要,则可以直接实现[OnMultiItemAdapterListener]接口.
     *
     * @constructor Create empty On multi item
     */
    abstract class OnMultiItem<T extends Object, V extends RecyclerView.ViewHolder> extends
            SimpleOnMultiItemAdapterListener<T, V> {
        private WeakReference<BaseMultiItemAdapter<T>> weakA;

        BaseMultiItemAdapter<T> adapter;

        public WeakReference<BaseMultiItemAdapter<T>> getWeakA() {
            return weakA;
        }

        public void setWeakA(WeakReference<BaseMultiItemAdapter<T>> weakA) {
            this.weakA = weakA;
        }

        public BaseMultiItemAdapter<T> getAdapter() {
            if (weakA != null) {
                return weakA.get();
            }
            return null;
        }

        public Context getContext() {
            if (weakA != null) {
                BaseMultiItemAdapter<T> itemAdapter = weakA.get();
                if (itemAdapter != null) {
                    return itemAdapter.getContext();
                }
            }
            return null;
        }

    }


    public interface OnItemViewTypeListener<T> {
        /**
         * 根据不同数据类型,返回不同的type值
         *
         * @param position
         * @param list
         * @return
         */
        int onItemViewType(int position, List<T> list);
    }
}