一句话总结:
适配器模式就像「电源转接头」—— 把不匹配的数据接口转换成 View 能理解的格式,Android 里 RecyclerView、ListView 都靠它变身数据展示大师!
一、适配器模式在 Android 的日常
核心作用:把五花八门的数据(数组、数据库查询结果等)转换成列表项(View)
类比场景:
- 数据:不同国家的电源插头(Type-C、Lightning、MicroUSB)
- 适配器:万能转接头
- View:手机充电口
二、源码级原理分析(以 RecyclerView 为例)
1. 核心类关系图
数据源(List/Cursor) → Adapter → RecyclerView
↑ |
└───── ViewHolder ←─────┘
2. 核心源码拆解
关键类:RecyclerView.Adapter
// frameworks/base/core/java/androidx/recyclerview/widget/RecyclerView.java
public abstract static class Adapter<VH extends ViewHolder> {
// 必须实现的三个方法
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
public abstract void onBindViewHolder(VH holder, int position);
public abstract int getItemCount();
// 数据变更通知机制(观察者模式)
private final AdapterDataObservable mObservable = new AdapterDataObservable();
public void registerAdapterDataObserver(AdapterDataObserver observer) {
mObservable.registerObserver(observer);
}
public void notifyDataSetChanged() {
mObservable.notifyChanged();
}
}
工作流程:
-
创建 ViewHolder:
// 系统在需要新 View 时调用 ViewHolder vh = adapter.onCreateViewHolder(parent, viewType);-
底层通过
LayoutInflater解析 XML →View -
典型实现:
public ViewHolder onCreateViewHolder(...) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_list, parent, false); return new MyViewHolder(view); }
-
-
绑定数据:
// 当列表项进入屏幕时触发 adapter.onBindViewHolder(holder, position);-
典型实现:
public void onBindViewHolder(MyViewHolder holder, int position) { String data = mDataList.get(position); holder.textView.setText(data); }
-
-
复用机制(性能关键):
RecyclerView维护一个 回收池(Recycler)- 滑动时离屏的 ViewHolder 存入回收池
- 新进入屏幕的项优先从回收池获取(避免频繁创建 View)
三、底层设计亮点
1. 观察者模式驱动数据更新
// 数据变化时通知 RecyclerView 刷新
public class MyAdapter extends RecyclerView.Adapter<...> {
private List<String> mData;
public void updateData(List<String> newData) {
mData = newData;
notifyDataSetChanged(); // 触发重绘
}
}
// 源码中的观察者实现
public static class AdapterDataObservable extends Observable<AdapterDataObserver> {
public void notifyChanged() {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
2. ViewHolder 模式优化性能
-
传统 ListView 的
getView()每次都要findViewById() -
RecyclerView 的 ViewHolder 缓存 View 引用:
class MyViewHolder extends RecyclerView.ViewHolder { TextView textView; public MyViewHolder(View itemView) { super(itemView); textView = itemView.findViewById(R.id.text); // 只执行一次 } }
3. 差异化视图类型(ViewType)
// 根据数据返回不同布局类型
public int getItemViewType(int position) {
return mData.get(position).isImportant() ? TYPE_HEADER : TYPE_NORMAL;
}
// onCreateViewHolder 根据类型创建不同 ViewHolder
public ViewHolder onCreateViewHolder(...) {
if (viewType == TYPE_HEADER) {
return new HeaderViewHolder(...);
} else {
return new NormalViewHolder(...);
}
}
四、与其他模式的对比
| 模式 | 核心区别 | Android 案例 |
|---|---|---|
| 适配器模式 | 接口转换,数据→View | RecyclerView.Adapter |
| 装饰者模式 | 动态增强功能,保持接口相同 | ContextWrapper → Context |
| 代理模式 | 控制访问,可能跨进程 | ActivityManagerProxy |
五、最佳实践与坑点
该做的:
- ViewHolder 用 static 内部类(防止内存泄漏)
- 分页加载大数据(避免一次性绑定所有数据)
- 使用 DiffUtil 智能刷新(减少不必要的重绘)
不该做的:
- 在 onBindViewHolder 执行耗时操作(导致列表卡顿)
- 在 Adapter 中写业务逻辑(应该放在 ViewModel/Presenter)
- 忘记调用 notifyXXX 方法(数据更新但 UI 不变)
六、总结口诀
「数据视图两茫茫,适配器来做红娘
ViewHolder 缓存在手,RecyclerView 性能无忧
观察通知变化有,DiffUtil 更智能」