目录
1. ArrayAdapter:简单文本列表(适合 ListView/Spinner)
2. SimpleAdapter:多元素列表(适合 ListView)
3. BaseAdapter:完全自定义列表(适合 ListView)
4. RecyclerView.Adapter:高性能复杂列表(适合 RecyclerView)
在 Android 开发中,Adapter(适配器)是数据与 UI 之间的桥梁,核心作用是将复杂数据(如列表、集合)按照指定的 UI 布局(如列表项)展示在可滚动控件(如 ListView、RecyclerView、Spinner 等)上。它解决了 “数据格式” 与 “UI 展示” 的解耦问题,让数据更新时无需手动操作 UI,只需更新数据源并通知适配器即可。
一、Adapter 核心原理
- 数据(Model):需要展示的数据(如
List<User>、List<String>)。 - UI 视图(View):列表项的布局(如
item_user.xml),定义每个列表项的样式。 - Adapter 角色:
- 管理数据(获取数据数量、单个数据);
- 将数据绑定到列表项视图(把数据填充到布局的控件中);
- 复用视图(避免频繁创建视图导致的性能问题)。
二、常见 Adapter 类型及典型用法
根据适配的控件和功能,Android 提供了多种内置 Adapter,也支持自定义 Adapter。以下是最常用的类型及用法:
1. ArrayAdapter:简单文本列表(适合 ListView/Spinner)
ArrayAdapter 是最简单的适配器,适用于数据为单一文本的场景(如字符串列表),可直接绑定到 ListView 或 Spinner,无需自定义布局(或仅需简单布局)。
适用场景:
- 展示纯文本列表(如设置项、选项列表)。
- 数据类型为
String或可转为字符串的对象(重写toString()方法)。
基本用法(绑定 ListView):
java
运行
// 1. 数据源(字符串列表)
List<String> data = new ArrayList<>();
data.add("张三");
data.add("李四");
data.add("王五");
// 2. 创建 ArrayAdapter(参数:上下文、列表项布局、数据)
// 注:android.R.layout.simple_list_item_1 是系统内置的简单文本布局
ArrayAdapter<String> adapter = new ArrayAdapter<>(
this,
android.R.layout.simple_list_item_1, // 列表项布局(仅一个 TextView)
data
);
// 3. 绑定到 ListView
ListView listView = findViewById(R.id.list_view);
listView.setAdapter(adapter);
自定义列表项布局:
若需简单修改文本样式(如颜色、大小),可自定义列表项布局(仅含 TextView):
xml
<!-- res/layout/item_text.xml -->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv_text"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:textColor="#FF0000"
android:textSize="18sp"/>
代码中使用自定义布局:
java
运行
ArrayAdapter<String> adapter = new ArrayAdapter<>(
this,
R.layout.item_text, // 自定义布局
R.id.tv_text, // 布局中 TextView 的 ID
data
);
listView.setAdapter(adapter);
2. SimpleAdapter:多元素列表(适合 ListView)
SimpleAdapter 支持多控件的列表项布局(如包含图片 + 文本 + 按钮),数据源需为 List<Map<String, Object>>(键值对集合),通过键名绑定布局中的控件。
适用场景:
- 列表项包含多种元素(如图标 + 标题 + 描述),且逻辑简单(无需复杂交互)。
基本用法:
java
运行
// 1. 数据源(每个元素是一个 Map,存储列表项的多组数据)
List<Map<String, Object>> data = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Map<String, Object> item = new HashMap<>();
item.put("icon", R.drawable.ic_user); // 图标资源 ID
item.put("name", "用户" + i); // 名称
item.put("desc", "这是用户" + i + "的描述"); // 描述
data.add(item);
}
// 2. 列表项布局(含 ImageView + 两个 TextView)
// res/layout/item_user.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center_vertical"
android:padding="16dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="40dp"
android:layout_height="40dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/tv_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="14sp"
android:textColor="#999"/>
</LinearLayout>
</LinearLayout>
// 3. 创建 SimpleAdapter(参数说明见注释)
SimpleAdapter adapter = new SimpleAdapter(
this,
data, // 数据源(List<Map>)
R.layout.item_user, // 列表项布局
new String[]{"icon", "name", "desc"}, // Map 中的键名数组(与数据对应)
new int[]{R.id.iv_icon, R.id.tv_name, R.id.tv_desc} // 布局中控件的 ID 数组(与键名一一对应)
);
// 4. 绑定到 ListView
ListView listView = findViewById(R.id.list_view);
listView.setAdapter(adapter);
局限性:
- 仅支持简单数据绑定,无法处理复杂交互(如按钮点击事件);
- 数据源必须是
List<Map>,灵活性较低。
3. BaseAdapter:完全自定义列表(适合 ListView)
BaseAdapter 是抽象类,需重写核心方法实现完全自定义,支持任意复杂的列表项布局和交互逻辑(如动态数据、按钮点击、多种布局类型),是 ListView 场景下最常用的适配器。
适用场景:
- 列表项布局复杂(多控件、动态样式);
- 需要处理列表项内部的交互(如按钮点击、复选框选择);
- 数据源类型复杂(如自定义对象
User、Product)。
核心方法:
继承 BaseAdapter 需重写以下 4 个方法:
getCount():返回数据总数(决定列表项数量);getItem(int position):返回指定位置的数据对象;getItemId(int position):返回指定位置的 ID(通常返回 position);getView(int position, View convertView, ViewGroup parent):核心方法,返回列表项视图,负责将数据绑定到视图。
基本用法(自定义对象 + 优化复用):
以展示 User 对象列表为例,包含性能优化(ViewHolder 模式):
java
运行
// 1. 自定义数据类(User)
public class User {
private int icon; // 头像资源 ID
private String name; // 姓名
private String phone; // 电话
public User(int icon, String name, String phone) {
this.icon = icon;
this.name = name;
this.phone = phone;
}
// getter 方法
public int getIcon() { return icon; }
public String getName() { return name; }
public String getPhone() { return phone; }
}
// 2. 列表项布局(res/layout/item_user.xml)
// 结构:ImageView(头像) + 两个 TextView(姓名、电话)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:gravity="center_vertical"
android:padding="16dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="40dp"
android:layout_height="40dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"/>
<TextView
android:id="@+id/tv_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:textSize="12sp"
android:textColor="#666"/>
</LinearLayout>
</LinearLayout>
// 3. 自定义 BaseAdapter(含 ViewHolder 优化)
public class UserAdapter extends BaseAdapter {
private Context context;
private List<User> dataList; // 数据源
// 构造方法:传入上下文和数据
public UserAdapter(Context context, List<User> dataList) {
this.context = context;
this.dataList = dataList;
}
// 返回数据总数
@Override
public int getCount() {
return dataList.size();
}
// 返回指定位置的数据
@Override
public Object getItem(int position) {
return dataList.get(position);
}
// 返回指定位置的 ID(通常用 position)
@Override
public long getItemId(int position) {
return position;
}
// 核心:获取列表项视图并绑定数据
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
// 1. 复用视图:convertView 为 null 时创建新视图,否则复用
if (convertView == null) {
// 加载布局
convertView = LayoutInflater.from(context)
.inflate(R.layout.item_user, parent, false);
// 创建 ViewHolder 存储控件引用
holder = new ViewHolder();
holder.ivIcon = convertView.findViewById(R.id.iv_icon);
holder.tvName = convertView.findViewById(R.id.tv_name);
holder.tvPhone = convertView.findViewById(R.id.tv_phone);
// 将 ViewHolder 绑定到 convertView
convertView.setTag(holder);
} else {
// 复用已有的 ViewHolder
holder = (ViewHolder) convertView.getTag();
}
// 2. 绑定数据到控件
User user = dataList.get(position);
holder.ivIcon.setImageResource(user.getIcon());
holder.tvName.setText(user.getName());
holder.tvPhone.setText(user.getPhone());
return convertView;
}
// ViewHolder 内部类:存储列表项中的控件引用,避免重复 findViewById(性能优化)
static class ViewHolder {
ImageView ivIcon;
TextView tvName;
TextView tvPhone;
}
}
// 4. 在 Activity 中使用适配器
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化数据
List<User> userList = new ArrayList<>();
userList.add(new User(R.drawable.ic_user1, "张三", "13800138000"));
userList.add(new User(R.drawable.ic_user2, "李四", "13900139000"));
// 创建适配器并绑定到 ListView
ListView listView = findViewById(R.id.list_view);
UserAdapter adapter = new UserAdapter(this, userList);
listView.setAdapter(adapter);
}
}
关键优化:ViewHolder 模式
- 问题:
getView会频繁调用(滚动列表时),若每次都通过findViewById获取控件,会导致性能损耗。 - 解决:用
ViewHolder存储控件引用,绑定到convertView的tag中,复用视图时直接从ViewHolder获取控件,避免重复查找。
4. RecyclerView.Adapter:高性能复杂列表(适合 RecyclerView)
RecyclerView 是 Android 推荐的列表控件(替代 ListView),其配套的 RecyclerView.Adapter 支持更灵活的布局(线性、网格、瀑布流)、动画效果和多类型列表项,性能更优。
适用场景:
- 复杂列表(如社交 APP 的动态流、电商商品列表);
- 需要多种列表项布局(如一条文本、一条图文、一条视频);
- 需支持动画(增删项动画、滚动动画)。
核心方法:
RecyclerView.Adapter 是抽象类,需定义一个 ViewHolder 子类,并重写 3 个核心方法:
onCreateViewHolder(ViewGroup parent, int viewType):创建ViewHolder(加载布局、初始化控件);onBindViewHolder(ViewHolder holder, int position):绑定数据到ViewHolder的控件;getItemCount():返回数据总数。
基本用法:
java
运行
// 1. 数据类(同 BaseAdapter 示例的 User)
public class User { ... }
// 2. 列表项布局(res/layout/item_user.xml,同上)
// 3. 自定义 ViewHolder(继承 RecyclerView.ViewHolder)
public class UserViewHolder extends RecyclerView.ViewHolder {
ImageView ivIcon;
TextView tvName;
TextView tvPhone;
public UserViewHolder(View itemView) {
super(itemView);
// 初始化控件
ivIcon = itemView.findViewById(R.id.iv_icon);
tvName = itemView.findViewById(R.id.tv_name);
tvPhone = itemView.findViewById(R.id.tv_phone);
}
}
// 4. 自定义 RecyclerView.Adapter
public class UserRecyclerAdapter extends RecyclerView.Adapter<UserViewHolder> {
private Context context;
private List<User> dataList;
public UserRecyclerAdapter(Context context, List<User> dataList) {
this.context = context;
this.dataList = dataList;
}
// 创建 ViewHolder(加载布局)
@Override
public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context)
.inflate(R.layout.item_user, parent, false);
return new UserViewHolder(view);
}
// 绑定数据到 ViewHolder
@Override
public void onBindViewHolder(UserViewHolder holder, int position) {
User user = dataList.get(position);
holder.ivIcon.setImageResource(user.getIcon());
holder.tvName.setText(user.getName());
holder.tvPhone.setText(user.getPhone());
}
// 返回数据总数
@Override
public int getItemCount() {
return dataList.size();
}
}
// 5. 在 Activity 中使用(需设置 LayoutManager)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化数据
List<User> userList = new ArrayList<>();
userList.add(new User(R.drawable.ic_user1, "张三", "13800138000"));
userList.add(new User(R.drawable.ic_user2, "李四", "13900139000"));
// 初始化 RecyclerView
RecyclerView recyclerView = findViewById(R.id.recycler_view);
// 设置布局管理器(必须!决定列表排列方式:线性、网格等)
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 设置适配器
UserRecyclerAdapter adapter = new UserRecyclerAdapter(this, userList);
recyclerView.setAdapter(adapter);
}
}
优势:
- 强制 ViewHolder:必须通过
ViewHolder管理控件,避免性能问题; - 支持多布局类型:重写
getItemViewType(int position)可返回不同布局类型,在onCreateViewHolder中加载对应布局; - 动画支持:默认支持增删项动画,可自定义;
- 布局灵活:通过
LayoutManager切换线性、网格(GridLayoutManager)、瀑布流(StaggeredGridLayoutManager)布局。
三、Adapter 通用操作:数据更新
当数据源发生变化(增、删、改)时,需通知适配器更新 UI,避免数据与视图不一致。不同 Adapter 的通知方法类似:
java
运行
// 1. 更新数据源(如添加一条数据)
dataList.add(new User(...));
// 2. 通知适配器更新(核心)
adapter.notifyDataSetChanged(); // 刷新所有数据(效率低,适合批量更新)
// 3. 局部更新(仅 RecyclerView.Adapter支持,效率高)
adapter.notifyItemInserted(position); // 插入一条数据
adapter.notifyItemRemoved(position); // 删除一条数据
adapter.notifyItemChanged(position); // 更新一条数据
注意:
notifyDataSetChanged()会刷新整个列表,效率较低;RecyclerView.Adapter的局部更新方法(如notifyItemInserted)仅刷新变化的项,性能更优。
四、总结
Adapter 是 Android 列表控件的核心组件,选择合适的 Adapter 可显著提升开发效率和性能:
| Adapter 类型 | 适用控件 | 适用场景 | 优势 | 局限性 |
|---|---|---|---|---|
ArrayAdapter | ListView/Spinner | 纯文本列表 | 用法简单,无需自定义 | 仅支持文本,灵活性低 |
SimpleAdapter | ListView | 多控件简单列表(无复杂交互) | 支持多元素布局,无需写适配器类 | 数据源必须为 List<Map>,不支持复杂交互 |
BaseAdapter | ListView | 复杂列表(自定义布局 + 交互) | 完全自定义,灵活度高 | 需手动实现优化(如 ViewHolder) |
RecyclerView.Adapter | RecyclerView | 高性能复杂列表(多布局、动画、网格等) | 强制优化,支持多布局和动画,性能最优 | 需配合 LayoutManager,代码稍多 |
实际开发中,RecyclerView.Adapter 是首选,因其功能全面、性能优异,适合绝大多数列表场景;简单文本列表可使用 ArrayAdapter 快速实现。核心原则是:数据与 UI 分离,通过适配器统一管理绑定逻辑,并做好视图复用优化。
362

被折叠的 条评论
为什么被折叠?



