上一节讲到继承举了Activity的列子,说明了使用继承在父类做一些共有的操作的好处。这一节我们将以RecyclerView的Adapter为列子,讲一下使用继承,把业务逻辑抽象出来,放在父类的好处。我们直接看例子:
T是泛型,使用泛型来表示我们列表的数据类型
public abstract class BaseRecyclerViewAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private View mHeaderView;
private View mFooterView;
protected ArrayList<T> mBeans = new ArrayList<T>();
private int mHeaderCount;
private int mFooterCount;
protected Context mContext;
public BaseRecyclerViewAdapter(Context context, ArrayList<T> beans){
mContext = context;
if(beans != null){
mBeans = beans;
}
}
//设置RecyclerView的头部
public void setHeaderView(View headerView){
mHeaderView = headerView;
}
//设置RecyclerView的尾部
public void setFooterView(View footerView){
mFooterView = footerView;
}
private static final int VIEW_TYPE_HEADER = 0;
private static final int VIEW_TYPE_FOOTER = 1;
private static final int VIEW_TYPE_NORMAL = 2;
//计算下一个item的视图类型
@Override
public int getItemViewType(int position) {
mHeaderCount = null == mHeaderView ? 0 : 1;
mFooterCount = null == mFooterView ? 0 : 1;
if(position < mHeaderCount){
return VIEW_TYPE_HEADER;
}else if(position >= (mHeaderCount + mBeans.size())){
return VIEW_TYPE_FOOTER;
}else{
return VIEW_TYPE_NORMAL;
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
if(viewType == VIEW_TYPE_HEADER){
viewHolder = new HearderFooterHolder(mHeaderView);
}else if(viewType == VIEW_TYPE_FOOTER){
viewHolder = new HearderFooterHolder(mFooterView);
}else{//getViewHolder是抽象方法可以根据具体的子类数据类型到子类自己定义ViewHolder
viewHolder = getViewHolder(parent);
}
return viewHolder;
}
//bindView()是抽象方法,可以到具体的子类去实现
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(getItemViewType(position) == VIEW_TYPE_NORMAL){
bindView(holder, position, position - mHeaderCount,mBeans.get(position - mHeaderCount));
}
}
@Override
public int getItemCount() {
return (null == mHeaderView ? 0 : 1) + mBeans.size() + (null == mFooterView ? 0 : 1);
}
public class HearderFooterHolder extends RecyclerView.ViewHolder{
public HearderFooterHolder(View itemView) {
super(itemView);
}
}
protected abstract RecyclerView.ViewHolder getViewHolder(ViewGroup parent);
protected abstract void bindView(RecyclerView.ViewHolder holder, int viewPosition, int dataIndex, T bean);
public int getHeaderCount(){
return null == mHeaderView ? 0 : 1;
}
public int getFooterCount(){
return null == mFooterView ? 0 : 1;
}
}
这个基类把适配器的itemCount的计算和headerView、footerView类型的判断逻辑都已经写好了,再借用bingView和getViewHolder等抽象方法让子类去实现具体的item布局。
使我们在写具体的适配器的时候只要继承他,就可以拥有添加头部尾部和自定义item布局的功能,而不用理会复杂的计算过程。
比如,到具体的适配器时就变得很简单
public class AdapterMyGame extends BaseRecyclerViewAdapter<AppLatestInfo> {
public AdapterMyGame(Context context, ArrayList<AppLatestInfo> mMyGame) {
super(context, mMyGame);
}
@Override
protected RecyclerView.ViewHolder getViewHolder(ViewGroup parent) {
return new MyGame(LayoutInflater.from(mContext).inflate(R.layout.item_my_mygame, parent, false));
}
@Override
protected void bindView(RecyclerView.ViewHolder holder, int viewPosition, final int dataIndex, final AppLatestInfo bean) {
MyGame viewHolder = (MyGame) holder;
GlideImageLoadUtils.displayImage(mContext,bean.gameIconUrl, viewHolder.mIvGameIcon, GlideImageLoadUtils.getGameIconOptions());
viewHolder.mTvGameName.setText(mBeans.get(dataIndex).getGameName());
final String packageName = mBeans.get(dataIndex).pkgName;
viewHolder.mBtnStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
CommonHelper.openApp(mContext, packageName, bean.gameId);
}
});
viewHolder.itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
ActivityUtils.startNormalGameDetailActivity(mContext, bean, "");
}
});
}
class MyGame extends RecyclerView.ViewHolder {
ImageView mIvGameIcon;//游戏icon
TextView mTvGameName;//游戏名称
TextView mTvGameTime;//游戏时间
TextView mBtnStart;//开始玩按钮
public MyGame(View convertView) {
super(convertView);
mIvGameIcon = (ImageView) convertView.findViewById(R.id.img_my_mygame);
mTvGameName = (TextView) convertView.findViewById(R.id.tv_gamename);
mTvGameTime = (TextView) convertView.findViewById(R.id.tv_gametime);
mBtnStart = (TextView) convertView.findViewById(R.id.my_mygame_play_button);
}
}
}