文章目录
-
- 1、自定义Adapter关键函数`getView()`标准写法
- 2、布局文件`list_item_user.xml`
- 3、解释
- 3、示例使用
- 4、结果
- 5、进一步优化和扩展
-
- [5.1. **优化性能:ViewHolder模式**](#5.1. 优化性能:ViewHolder模式)
- [5.2. **处理多种类型的视图**](#5.2. 处理多种类型的视图)
- [5.3. **使用RecyclerView.Adapter**](#5.3. 使用RecyclerView.Adapter)
- 6、RecyclerView使用示例
- 7、结果
- 8、结论
在Android开发中,自定义Adapter是非常常见的,用于为ListView、GridView、RecyclerView等视图提供数据。自定义Adapter的关键函数是 getView()
方法,它负责为每一项数据创建和返回一个View。以下是一个标准的自定义Adapter及其 getView()
方法的详细用例和解释。
1、自定义Adapter关键函数getView()
标准写法
假设我们有一个简单的用户数据类:
java
public class User {
private String name;
private String email;
public User(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
}
自定义Adapter的实现:
java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
public class UserAdapter extends BaseAdapter {
private Context context;
private List<User> userList;
private LayoutInflater inflater;
public UserAdapter(Context context, List<User> userList) {
this.context = context;
this.userList = userList;
this.inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return userList.size();
}
@Override
public Object getItem(int position) {
return userList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
// Inflate the custom layout
convertView = inflater.inflate(R.layout.list_item_user, parent, false);
// Initialize the ViewHolder
viewHolder = new ViewHolder();
viewHolder.nameTextView = convertView.findViewById(R.id.nameTextView);
viewHolder.emailTextView = convertView.findViewById(R.id.emailTextView);
// Store the holder with the view
convertView.setTag(viewHolder);
} else {
// Retrieve the view holder
viewHolder = (ViewHolder) convertView.getTag();
}
// Get the current user
User currentUser = (User) getItem(position);
// Set the user details to the view
viewHolder.nameTextView.setText(currentUser.getName());
viewHolder.emailTextView.setText(currentUser.getEmail());
return convertView;
}
// ViewHolder pattern to optimize list view performance
static class ViewHolder {
TextView nameTextView;
TextView emailTextView;
}
}
2、布局文件list_item_user.xml
这是自定义的布局文件,定义了每个列表项的布局:
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="wrap_content"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:id="@+id/nameTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textColor="@android:color/black" />
<TextView
android:id="@+id/emailTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="@android:color/darker_gray" />
</LinearLayout>
3、解释
-
ViewHolder模式:
ViewHolder
是一个静态内部类,用来缓存View。这样避免了每次调用getView()
方法时都调用findViewById()
方法,提高了ListView的性能。
-
getView()
方法:convertView
参数是用于重用旧视图的。为了性能优化,如果convertView
不为null,则可以重用。- 如果
convertView
为null,意味着这是第一次创建这个视图,需要使用LayoutInflater
去加载布局,并初始化ViewHolder
。 - 使用
convertView.setTag(viewHolder)
来存储ViewHolder
对象,方便后续重用。 - 使用
convertView.getTag()
来获取缓存的ViewHolder
对象,避免重复调用findViewById()
。 - 最后,将当前项的数据设置到
ViewHolder
中的各个控件上。
3、示例使用
假设在某个Activity中使用这个Adapter:
java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = findViewById(R.id.listView);
// 示例数据
List<User> users = new ArrayList<>();
users.add(new User("Alice", "alice@example.com"));
users.add(new User("Bob", "bob@example.com"));
// 设置自定义Adapter
UserAdapter adapter = new UserAdapter(this, users);
listView.setAdapter(adapter);
}
}
4、结果
运行应用时,ListView
将显示用户列表,每行包含用户名和电子邮件地址。通过使用ViewHolder模式,确保了列表的高效滚动和视图重用。
5、进一步优化和扩展
5.1. 优化性能:ViewHolder模式
在大数据集的情况下,ViewHolder
模式是非常重要的优化技术。它通过缓存View引用,减少了不必要的视图查找操作。
java
// Adapter类中
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
// Inflate the custom layout
convertView = inflater.inflate(R.layout.list_item_user, parent, false);
// Initialize the ViewHolder
viewHolder = new ViewHolder();
viewHolder.nameTextView = convertView.findViewById(R.id.nameTextView);
viewHolder.emailTextView = convertView.findViewById(R.id.emailTextView);
// Store the holder with the view
convertView.setTag(viewHolder);
} else {
// Retrieve the view holder
viewHolder = (ViewHolder) convertView.getTag();
}
// Get the current user
User currentUser = (User) getItem(position);
// Set the user details to the view
viewHolder.nameTextView.setText(currentUser.getName());
viewHolder.emailTextView.setText(currentUser.getEmail());
return convertView;
}
// ViewHolder pattern to optimize list view performance
static class ViewHolder {
TextView nameTextView;
TextView emailTextView;
}
5.2. 处理多种类型的视图
有时我们需要在一个列表中展示不同类型的视图,可以通过覆盖getViewTypeCount()
和getItemViewType(int position)
来实现。
java
@Override
public int getViewTypeCount() {
// 两种不同的视图类型
return 2;
}
@Override
public int getItemViewType(int position) {
User user = (User) getItem(position);
if (user.isSpecialUser()) {
return 0; // 特殊用户类型
} else {
return 1; // 普通用户类型
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
ViewHolder viewHolder;
if (convertView == null) {
switch (viewType) {
case 0:
// 特殊用户视图
convertView = inflater.inflate(R.layout.special_user_item, parent, false);
viewHolder = new SpecialViewHolder();
viewHolder.specialTextView = convertView.findViewById(R.id.specialTextView);
break;
case 1:
// 普通用户视图
convertView = inflater.inflate(R.layout.list_item_user, parent, false);
viewHolder = new ViewHolder();
viewHolder.nameTextView = convertView.findViewById(R.id.nameTextView);
viewHolder.emailTextView = convertView.findViewById(R.id.emailTextView);
break;
}
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// 填充数据
User currentUser = (User) getItem(position);
if (viewType == 0) {
((SpecialViewHolder) viewHolder).specialTextView.setText(currentUser.getSpecialInfo());
} else {
viewHolder.nameTextView.setText(currentUser.getName());
viewHolder.emailTextView.setText(currentUser.getEmail());
}
return convertView;
}
// 普通ViewHolder
static class ViewHolder {
TextView nameTextView;
TextView emailTextView;
}
// 特殊用户ViewHolder
static class SpecialViewHolder extends ViewHolder {
TextView specialTextView;
}
5.3. 使用RecyclerView.Adapter
如果你的项目使用RecyclerView,而不是ListView或GridView,可以使用RecyclerView.Adapter来实现自定义Adapter。RecyclerView比ListView更强大和灵活,并且内置了ViewHolder模式。
java
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserViewHolder> {
private List<User> userList;
public UserAdapter(List<User> userList) {
this.userList = userList;
}
@Override
public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_user, parent, false);
return new UserViewHolder(itemView);
}
@Override
public void onBindViewHolder(UserViewHolder holder, int position) {
User currentUser = userList.get(position);
holder.nameTextView.setText(currentUser.getName());
holder.emailTextView.setText(currentUser.getEmail());
}
@Override
public int getItemCount() {
return userList.size();
}
public static class UserViewHolder extends RecyclerView.ViewHolder {
public TextView nameTextView;
public TextView emailTextView;
public UserViewHolder(View view) {
super(view);
nameTextView = view.findViewById(R.id.nameTextView);
emailTextView = view.findViewById(R.id.emailTextView);
}
}
}
6、RecyclerView使用示例
java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recyclerView);
// 示例数据
List<User> users = new ArrayList<>();
users.add(new User("Alice", "alice@example.com"));
users.add(new User("Bob", "bob@example.com"));
// 设置布局管理器
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 设置自定义Adapter
UserAdapter adapter = new UserAdapter(users);
recyclerView.setAdapter(adapter);
}
}
7、结果
在使用RecyclerView时,列表项的视图会更高效地被管理和重用,提供更平滑的滚动体验。
8、结论
无论是ListView还是RecyclerView,自定义Adapter的getView()
方法(或onBindViewHolder()
方法)都是核心部分,负责创建和绑定视图。使用ViewHolder模式可以显著提高性能。对于复杂的列表,可以通过实现不同的视图类型来满足需求。RecyclerView提供了更灵活和高效的实现,推荐在新的项目中使用。