一个点背的java抽象类的问题

在使用RecyclerView的时候遇到了一个很坑的问题,记录这个大坑!

首先,在使用RecyclerView.Adapter的时候定义了一个BaseListAdapter,代码如下:

public abstract class BaseListAdapter<T extends BaseEntity> extends RecyclerView.Adapter<BaseListAdapter.ViewHolder> {

    public static final int ITEM_LAYOUT_NORMAL = 0;
    public static final int ITEM_LAYOUT_SIMPLE = 1;

    protected List<T> mList;
    protected Context mContext;
    private int mType;

    public int getType(){
        return ITEM_LAYOUT_NORMAL;
    }

    public BaseListAdapter(Context context, List<T> list){
        super();
        mContext = context;
        mList = list;
        mType = getType();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        int layout = -1;
        switch (mType){
            case ITEM_LAYOUT_NORMAL:
                layout = R.layout.item_list_normal;
                break;
            case ITEM_LAYOUT_SIMPLE:
                layout = R.layout.item_list_simple;
                break;
        }

        View v = LayoutInflater.from(parent.getContext()).inflate(layout, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public int getItemCount() {
        return mList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder{
        public TextView title;

        public TextView vote;
        public ImageView photo;
        public TextView content;
        public ImageView createrIcon;
        public TextView creater;
        public TextView date;

        public ImageView[] image;

        public ViewHolder(View itemView) {
            super(itemView);

            if (mType == ITEM_LAYOUT_NORMAL) {
                title = (TextView) itemView.findViewById(R.id.item_title);
                vote = (TextView) itemView.findViewById(R.id.item_vote);
                photo = (ImageView) itemView.findViewById(R.id.item_photo);
                content = (TextView) itemView.findViewById(R.id.item_content);
                createrIcon = (ImageView) itemView.findViewById(R.id.item_user_photo);
                creater = (TextView) itemView.findViewById(R.id.item_creater);
                date = (TextView) itemView.findViewById(R.id.item_date);
            }

            if (mType == ITEM_LAYOUT_SIMPLE) {
                title = (TextView) itemView.findViewById(R.id.item_title);
                image[0] = (ImageView) itemView.findViewById(R.id.item_image1);
                image[1] = (ImageView) itemView.findViewById(R.id.item_image2);
                image[2] = (ImageView) itemView.findViewById(R.id.item_image3);
                image[3] = (ImageView) itemView.findViewById(R.id.item_image4);
                image[4] = (ImageView) itemView.findViewById(R.id.item_image5);
            }
        }
    }
}

其中定义的ViewHolder是一个内部类,RecyclerView.Adapter在继承时需要指定泛型,这里看下RecyclerView.Adapter的定义:

public static abstract class Adapter<VH extends ViewHolder> {
    private final AdapterDataObservable mObservable = new AdapterDataObservable();
    private boolean mHasStableIds = false;

    public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

    public abstract void onBindViewHolder(VH holder, int position);

    public void onBindViewHolder(VH holder, int position, List<Object> payloads) {
        onBindViewHolder(holder, position);
    }

    public final VH createViewHolder(ViewGroup parent, int viewType) {
        TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG);
        final VH holder = onCreateViewHolder(parent, viewType);
        holder.mItemViewType = viewType;
        TraceCompat.endSection();
        return holder;
    }

    public final void bindViewHolder(VH holder, int position) {
        holder.mPosition = position;
        if (hasStableIds()) {
            holder.mItemId = getItemId(position);
        }
        holder.setFlags(ViewHolder.FLAG_BOUND,
                ViewHolder.FLAG_BOUND | ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID
                        | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN);
        TraceCompat.beginSection(TRACE_BIND_VIEW_TAG);
        onBindViewHolder(holder, position, holder.getUnmodifiedPayloads());
        holder.clearPayload();
        TraceCompat.endSection();
    }

    public int getItemViewType(int position) {
        return 0;
    }
    .......

这里抽象方法onBindViewHolder使用该泛型作为第一个参数。

最后,定义了一个具体的实现adapter,如下:

public class TopicListAdapter extends BaseListAdapter<Topic> {

    public TopicListAdapter(Context context, List<Topic> list) {
        super(context, list);
    }

    @Override
    public int getType() {
        return ITEM_LAYOUT_SIMPLE;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Topic entity = mList.get(position);

        holder.title.setText(entity.title);

        int index = 0;
        if (entity.images != null && entity.images.size() > 0) {
            for (String url : entity.images) {
                if (index == 5) {
                    break;
                }
                Glide.with(mContext)
                        .load(url)
                        .diskCacheStrategy(DiskCacheStrategy.ALL)
                        .placeholder(R.drawable.img_circle_placeholder)
                        .error(R.drawable.default_photo)
                        .centerCrop()
                        .transform(new CropCircleTransformation(mContext))
                        .into(holder.image[index]);
                index++;
            }
        } else {
            for (int i=0;i<5;i++){
                holder.image[i].setVisibility(View.GONE);
            }
        }
    }
}

都没有问题,实现类继承抽象类并实现了所有抽象方法。

但是,编译报错!!

居然报的是TopicListAdapter 类中没有实现onBindViewHolder方法,XXX啊!明明实现了,是不是javac有问题啊!

这问题搞的我都怀疑编译器是不是有问题了!!

这里的问题实在是太隐蔽了!上面在抽象类中有一个泛型,这个泛型正好是抽象方法onBindViewHolder的第一个参数类型-》BaseListAdapter.ViewHolder,所以抽象方法的定义是

public abstract void onBindViewHolder(BaseListAdapter.ViewHolder holder, int position);

,而TopicListAdapter中实现的方法是这样的:

public void onBindViewHolder(ViewHolder holder, int position) {
。。。。。
}

有什么不一样?

ViewHolder没有指定是谁的内部类啊!!

改成:

public void onBindViewHolder(BaseListAdapter.ViewHolder holder, int position) {
。。。。。
}

KO!

这里TopicListAdapter 在继承时会继承BaseListAdapter中的内部类ViewHolder,也就是在TopicListAdapter 中也会有ViewHolder这个内部类,所以如果不指定是BaseListAdapter类中的ViewHolder则方法其实是这样定义的:

public void onBindViewHolder(TopicListAdapter.ViewHolder holder, int position) {}

很显然这不是抽象类中定义的方法(参数不一致),所以就造成无法覆盖!

ide没有没提示该错误!

转载于:https://my.oschina.net/buobao/blog/651007

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值