一、BaseAdapter简介
BaseAdapter是Android应用程序中经常用到的基础数据适配器,它的主要用途是将一组数据传到像ListView、Spinner、Gallery及GridView等UI显示组件,它是继承自接口类Adapter。
下图表示了数据源Data Source、数据适配器Adapter以及显示控件ListView之间的关系。
使用适配器模式从将数据的来源和数据的显示进行了解耦,降低了代码的耦合度,也使得程序代码变的容易扩展。
二、ListView的显示与缓存机制
listview的加载一开始不会将所有的item项都加载出来,他只会加载可视的那部分,当我们将listview向上滑动时,item1被移除了可视范围,则item1会被存入View的缓冲池convertView中,然后item8才会被加载出来。
三、BaseAdapter比较关键的几个API
1.public int getCount():适配器中数据集的数据个数
2.public Object getItem(int position):获取数据集中与所给索引对应的数据项
3.public long getItemld(int position):获取指定行对应的ID
4.public View getView(int position, View convertView, ViewGroup parent):取每一个Item显示内容
四、BaseAdapter使用实例
1.创建布局文件
在activity_main.xml文件中添加以下代码:
<ListView
android:id="@+id/listview_main"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
创建item.xml用于显示ListView每一项的格式:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="30dp"
android:text="Title"
android:layout_toEndOf="@+id/imageView"
android:gravity="center"
android:textSize="25sp"/>
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="30dp"
android:text="Content what what what what"
android:layout_toEndOf="@+id/imageView"
android:layout_below="@id/textView1"
android:gravity="center_vertical"
android:textSize="20sp"/>
</RelativeLayout>
接着,创建我们listview中要显示的数据源,新建一个Bean类
public class ItemBean {
public int itemImageResID;
public String itemTitle;
public String itemContent;
public ItemBean(int itemImageResID, String itemTitle, String itemContent) {
this.itemImageResID = itemImageResID;
this.itemTitle = itemTitle;
this.itemContent = itemContent;
}
}
然后在MainActivity里面创建一个List的实例
List<ItemBean> itemBeanList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
itemBeanList.add(new ItemBean(
R.mipmap.ic_launcher, "标题", "我是正文,我是正文,我是正文"));
}
接着新建一个数据适配器Adapter类继承自BaseAdapter,并实现父类的方法,即刚才第三点提到的几个API,比较重要的就是getView()方法的重写。通过ViewHolder内部类来实现显示数据和视图的缓存,避免了每次通过findViewById寻找控件。以下是MyAdapter类的代码,具体的解释写在代码注释中:
public class MyAdapter extends BaseAdapter {
// 创建bean对象用于封装数据
private List<ItemBean> mList;
private LayoutInflater mInflater;
public MyAdapter(Context context, List<ItemBean> list) {
// 加载布局管理器
mInflater = LayoutInflater.from(context);
mList = list;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View converView, ViewGroup viewGroup) {
ViewHolder viewHolder;
// 利用了ListView的缓存特性,如果没有缓存(convertView)才创建新的View
if (converView == null) {
// 利用viewHolder中的对象,找到布局中的组件
viewHolder = new ViewHolder();
// 将xml布局转换为view对象
converView = mInflater.inflate(R.layout.item, null);
viewHolder.imageView = (ImageView) converView.findViewById(R.id.imageView);
viewHolder.title = (TextView) converView.findViewById(R.id.tv_title);
viewHolder.content = (TextView) converView.findViewById(R.id.tv_content);
// 建立起converView和viewHolder的联系
converView.setTag(viewHolder);
} else {
// 直接从viewHolder中取出实例
viewHolder = (ViewHolder) converView.getTag();
}
ItemBean bean = mList.get(position);
viewHolder.imageView.setImageResource(bean.itemImageResID);
viewHolder.title.setText(bean.itemTitle);
viewHolder.content.setText(bean.itemContent);
return converView;
}
// 将实例对象封装到viewHolder中,避免重复的findViewById的操作
class ViewHolder {
public ImageView imageView;
public TextView title;
public TextView content;
}
}
最终实现的效果如下