You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过泛型在BaseAdapter基类内部获取继承它的子类?

嘿,这个问题我熟!咱们可以通过让BaseAdapter成为泛型类来彻底解决每次要指定具体子类的麻烦,既能保证类型安全,又能让基类提供通用的刷新逻辑。下面一步步来实现:

第一步:重构BaseAdapter为泛型基类

首先把BaseAdapter改成泛型类,绑定数据类型和ViewHolder类型,同时实现通用的refreshData方法——子类可以直接用,也能按需重写扩展:

import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;

public abstract class BaseAdapter<T, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<VH> {
    protected List<T> mData;

    // 构造方法初始化数据
    public BaseAdapter(List<T> data) {
        this.mData = data != null ? data : new ArrayList<>();
    }

    // 通用刷新方法,子类可重写
    public void refreshData(List<T> newData) {
        mData.clear();
        mData.addAll(newData);
        notifyDataSetChanged(); // 也可以替换为DiffUtil实现局部刷新,这里先简化
    }

    // 子类必须实现的核心抽象方法
    @Override
    public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

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

    @Override
    public int getItemCount() {
        return mData.size();
    }
}
第二步:子类继承泛型基类

比如你的TopicAdapter,继承的时候只需要指定对应的数据类型和ViewHolder类型就行,完全不用重复写刷新逻辑(除非你需要自定义):

public class TopicAdapter extends BaseAdapter<Topic, TopicViewHolder> {
    public TopicAdapter(List<Topic> data) {
        super(data);
    }

    @Override
    public TopicViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // 这里写你的ViewHolder创建逻辑,比如加载布局
        return new TopicViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_topic, parent, false));
    }

    @Override
    public void onBindViewHolder(TopicViewHolder holder, int position) {
        // 绑定数据到ViewHolder,直接用mData获取数据
        Topic topic = mData.get(position);
        holder.tvTitle.setText(topic.getTitle());
        // ...其他绑定逻辑
    }

    // 如果需要自定义刷新逻辑,重写refreshData即可
    @Override
    public void refreshData(List<Topic> newData) {
        super.refreshData(newData);
        // 比如添加额外的状态更新、动画等
    }
}
第三步:优化外部调用代码

现在你再也不用判断具体是哪个子类了,只需要判断是否是BaseAdapter的实例,通过泛型安全转换后直接调用refreshData:

方式1:直接转换调用

RecyclerView.Adapter adapter = mRecyclerView.getAdapter();
if (adapter instanceof BaseAdapter) {
    // 这里指定数据类型,比如Topic,就能直接调用refreshData
    ((BaseAdapter<Topic, ?>) adapter).refreshData(topicDetails);
} else {
    // 如果Adapter不存在,直接创建对应的BaseAdapter子类
    BaseAdapter<Topic, TopicViewHolder> newAdapter = new TopicAdapter(new ArrayList<>());
    newAdapter.refreshData(topicDetails);
    mRecyclerView.setAdapter(newAdapter);
}

方式2:封装泛型工具方法(更优雅)

如果不想每次都写强转,可以封装一个工具方法,简化调用:

@SuppressWarnings("unchecked")
private <T, VH extends RecyclerView.ViewHolder> BaseAdapter<T, VH> getBaseAdapter(RecyclerView recyclerView) {
    RecyclerView.Adapter adapter = recyclerView.getAdapter();
    return adapter instanceof BaseAdapter ? (BaseAdapter<T, VH>) adapter : null;
}

然后调用就超简洁:

BaseAdapter<Topic, TopicViewHolder> adapter = getBaseAdapter(mRecyclerView);
if (adapter != null) {
    adapter.refreshData(topicDetails);
} else {
    adapter = new TopicAdapter(new ArrayList<>());
    adapter.refreshData(topicDetails);
    mRecyclerView.setAdapter(adapter);
}
核心思路

通过泛型让BaseAdapter和子类绑定具体的数据类型,既避免了无意义的强转,又让基类能提供通用的刷新逻辑——所有继承BaseAdapter的子类都能直接复用这个能力,你再也不用在代码里写死具体的子类名称啦!

内容的提问来源于stack exchange,提问作者bycfly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:46:22