package com.netease.nim.uikit.common.ui.recyclerview.adapter;
import android.support.annotation.LayoutRes;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.ViewGroup;
import com.netease.nim.uikit.common.ui.recyclerview.holder.BaseViewHolder;
import com.netease.nim.uikit.common.ui.recyclerview.holder.RecyclerViewHolder;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class BaseMultiItemQuickAdapter<T, K extends BaseViewHolder> extends BaseQuickAdapter<T, K> {
/**
* viewType->layoutResId
*/
private SparseArray<Integer> layouts;
/**
* viewType->view holder class
*/
private SparseArray<Class<? extends RecyclerViewHolder>> holderClasses;
/**
* viewType->view holder instance
*/
private Map<Integer, Map<String, RecyclerViewHolder>> multiTypeViewHolders;
/**
* get view type from data item
*
* @param item
* @return
*/
protected abstract int getViewType(T item);
/**
* get view holder unique key from data item
*
* @param item
* @return
*/
protected abstract String getItemKey(T item);
public BaseMultiItemQuickAdapter(RecyclerView recyclerView, List<T> data) {
super(recyclerView, data);
}
/**
* add viewType->layoutResId, viewType->ViewHolder.class
*
* @param type view type
* @param layoutResId
* @param viewHolderClass
*/
protected void addItemType(int type, @LayoutRes int layoutResId, Class<? extends RecyclerViewHolder> viewHolderClass) {
// layouts
if (layouts == null) {
layouts = new SparseArray<>();
}
layouts.put(type, layoutResId);
// view holder class
if (holderClasses == null) {
holderClasses = new SparseArray<>();
}
holderClasses.put(type, viewHolderClass);
// view holder
if (multiTypeViewHolders == null) {
multiTypeViewHolders = new HashMap<>();
}
multiTypeViewHolders.put(type, new HashMap<String, RecyclerViewHolder>());
}
@Override
protected int getDefItemViewType(int position) {
return getViewType(mData.get(position));
}
@Override
protected K onCreateDefViewHolder(ViewGroup parent, int viewType) {
return createBaseViewHolder(parent, getLayoutId(viewType));
}
@Override
protected void convert(final K baseHolder, final T item, final int position, boolean isScrolling) {
/**
* 注意:baseHolder对应的是某一行的View的缓存,与item不一定是一一对应的。即同一个item,在不同的行,回调的baseHolder不一样。
* 例如:第一行:s1-> baseHolder01 第二行 s2->baseHolder02。
* 把s2置顶,则第一行:s2->baseHolder01,第二行:s1->baseHolder02。
*
* 而我们的设计:item与RecyclerViewHolder是一一对应的。因此每次convert都需要拿当前回调的baseHolder进行convert,
* RecyclerViewHolder可以从baseHolder中取出该行View所有的子View进行数据绑定(相当于需要经历inflate->refresh的过程)。
*/
final String key = getItemKey(item);
final int viewType = baseHolder.getItemViewType();
RecyclerViewHolder h = multiTypeViewHolders.get(viewType).get(key);
if (h == null) {
// build
try {
Class<? extends RecyclerViewHolder> cls = holderClasses.get(viewType);
Constructor c = cls.getDeclaredConstructors()[0]; // 第一个显式的构造函数
c.setAccessible(true);
h = (RecyclerViewHolder) c.newInstance(new Object[]{this});
multiTypeViewHolders.get(viewType).put(key, h);
} catch (Exception e) {
e.printStackTrace();
}
}
// convert
if (h != null) {
h.convert(baseHolder, item, position, isScrolling);
}
}
@Override
protected void onRemove(final T item) {
super.onRemove(item);
// 移除holder
multiTypeViewHolders.get(getViewType(item)).remove(getItemKey(item));
}
private int getLayoutId(int viewType) {
return layouts.get(viewType);
}
}