我们在前面三篇文章分别介绍了ArrayAdapter和SimpleAdapter的使用,可以先总结一下:
1)ArrayAdapter,是一个跟Array结构对应的Adapter,所以它展示的内容取决于Array里面装的对象,在默认或者大部分情况下,如果一个list只是要用来展示一些文字方面的效果,比如文章列表,联系人列表等比较简洁的描述,这是个最好的选择。当然,我们也可以通过继承它来自定义一个Adapter。
2)SimpleAdapter,需要1)我们自定义item的布局,2)需要我们将数据源封装成一个List<Map<String,?>>结构的列表中去,3)要将布局中的控件跟map中的数据对应起来。SimpleAdapter可以根据我们的需要,实现比较灵活的布局和效果,这方面是ArrayAdapter比不上的。
Android已经帮我们实现了这两个Adapter的逻辑,并封装得很好,好到我们只需要创建一个对象就可以用了。但有时候,包装得太过的东西总是麻烦,灵活性还是不够。
而在日常的开发中,我们经常会用到的,更多的是BaseAdapter,这个抽象类,而ArrayAdapter和SimpleAdapter,其实也是BaseAdapter的子类。
BaseAdapter
实现BaseAdapter,就比较麻烦一点,因为比较Base,所以需要我们实现的东西会比较多。
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
// TODO Auto-generated method stub
return 0;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
return null;
}
}
首先我们要创建一个自定义的MyAdapter,并继承BaseAdapter,并且需要实现其几个基本的方法:
1)getCount():返回这个BaseAdapter处理数据源的总数,这个决定了下面会call多少次getView方法。
2)getItem():返回数据源中的某个位置的对象。
3)getItemId():返回数据源中的某个位置的对象的id。
4)getView():这个方法是整个Adapter方法中最重要的方法,它决定了我们在list上面展示的布局效果。
下面我们来实际应用一下吧。
我们还是采用上一篇文章中simpleadpater.xml的布局,如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:padding="5dip"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:id="@+id/imageView1"
android:layout_width="80dip"
android:layout_height="60dip"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:contentDescription="testing"/>
<TextView android:id="@+id/tvTitle"
android:layout_width="80dip"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/imageView1"
android:layout_alignTop="@+id/imageView1"/>
<TextView android:id="@+id/tvContent"
android:layout_width="80dip"
android:layout_height="wrap_content"
android:layout_below="@+id/tvTitle"
android:layout_toRightOf="@+id/imageView1"
android:layout_alignBottom="@+id/imageView1"/>
</RelativeLayout>
然后我们来实现我们的Adapter,代码如下:
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
return titles.length;//返回titles.length,总共是6个。
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return titles[position];
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//将布局inflate出来,然后获得布局上的控件,设置值
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.simpleadapter, null);
ImageView imageView = (ImageView) view.findViewById(R.id.imageView1);
imageView.setImageResource(drawableIds[position]);
TextView tvTitle = (TextView) view.findViewById(R.id.tvTitle);
tvTitle.setText("ba title " + position);
TextView tvContent = (TextView) view.findViewById(R.id.tvContent);
tvContent.setText("ba content" + position);
return view;
}
}
看效果图:
其实可以看到,效果跟simpleAdapter是一样的,那么如果我们返回10000个呢?我们改一下代码:
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
return 10000;
}
...
@Override
public View getView(int position, View convertView, ViewGroup parent) {
...
imageView.setImageResource(drawableIds[position % 6]);//取模,因为图片有限
...
}
}
下面是效果图:
但其实这样做实现,效率很差的,像我们现在有10000个item,它就要创建10000个view出来,多恐怖的事情,而我们在手机屏幕不管如何,也就看到那么几个item,哪里需要这么多呢?所以,参考ArrayAdapter和SimpleAdapter的getView的实现:
public View getView(int position, View convertView, ViewGroup parent) {
return createViewFromResource(position, convertView, parent, mResource);
}
private View createViewFromResource(int position, View convertView, ViewGroup parent,
int resource) {
View view;
TextView text;
if (convertView == null) {
view = mInflater.inflate(resource, parent, false);
} else {
view = convertView;
}
可以看到,会首先去判断convertView是否为null,当其为null的时候,才去重新创建一个view,不是的话,就直接用convertView。那么这个convertView是什么东西呢?其实它就是刚刚离开屏幕的那个View,所以我们可以复用它,这样我们就可以极大极大地减少这个view的创建。
所以我们把代码改成:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view ;
if(convertView == null){
view = LayoutInflater.from(MainActivity.this).inflate(R.layout.simpleadapter, null);
}else{
view = convertView;
}
...
}
这一点,可以说极大地优化了这个listView的性能,尤其是我们在加载图片这种很耗内存的资源的时候,这个效果更加明显。
不过这还不够,因为获得这个view之后,每次还需要通过 view.findViewById 来获得view里面的控件,findViewById的成本也是非常之高的,那么有什么办法呢?
一般来说,就是ViewHolder的应用了。
public View getView(int position, View convertView, ViewGroup parent) {
View view ;
ViewHolder viewHolder;
if(convertView == null){
view = LayoutInflater.from(MainActivity.this).inflate(R.layout.simpleadapter, null);
ImageView imageView = (ImageView) view.findViewById(R.id.imageView1);
TextView tvTitle = (TextView) view.findViewById(R.id.tvTitle);
TextView tvContent = (TextView) view.findViewById(R.id.tvContent);
viewHolder = new ViewHolder(imageView, tvTitle, tvContent);
view.setTag(viewHolder);
}else{
view = convertView;
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.imageView.setImageResource(drawableIds[position % 6]);
viewHolder.tvTitle.setText("ba title " + position);
viewHolder.tvContent.setText("ba content" + position);
return view;
}
}
class ViewHolder {
public ViewHolder(ImageView imageView, TextView tvTitle, TextView tvContent){
this.imageView = imageView;
this.tvTitle = tvTitle;
this.tvContent = tvContent;
}
ImageView imageView;
TextView tvTitle;
TextView tvContent;
}
我们可以在从view中获得的这几个控件放到一个viewHolder的对象中,并将其设置给view的Tag属性,这样下一次再重复利用这个view的时候,就不必再通过findViewById来获得控件 ,而是可以直接通过viewHolder来获得对应的控件。
关于BaseAdapter的应用,基本上也就是这样。
关于ListView中几种Adapter的应用,几篇文章总算做了个总结,希望能够对大家有个帮助。
分享到:
相关推荐
ListView与BaseAdapter的配套使用 理解android 中adapter适配的作用 以及ListView的优化方式
很多朋友都来问我,如果要做一个列表,列表的每一项都是TextView和ImageView(或者其他组件)的组合,怎么做,现在,我就写一个简单的范例
android中ArrayAdapter SimpleAdapter BaseAdapter 的使用
该例中包含了常用的Adapter的使用,如baseadapter、simpleAdapter、SimlpeCursorAdapter和ArrayAdapter,例子写在一个工程中的。请注意切换清单文件中启动的Activity。
android中adapter整理,包括Baseadapter,Simpleadapter,cursoradapter的详细使用说明
Android-扩展BaseAdapter实现progressBar下载 * 该Demo涉及了BaseAdapter,ProgressBar,Handler,Thread,线程池; * * Android-扩展BaseAdapter实现progressBar下载 * 1.创建listview的xml * 2.创建listview中...
基于Eclipse开发平台,Android中使用ListView和三种适配器(ArrayAdaper,SimpleAdapter,BaseAdapter)实现数据的填充。
主要为大家详细介绍了Kotlin编写Android适配器Adapter的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
android-Stupid-Adapter?1,BaseAdapter、RecyclerView和一、适配器.zip
NULL 博文链接:https://chaowen0668.iteye.com/blog/1017481
baseadapter
android-Stupid-Adapter 一个比较蠢的adapter,一切只是为了少写两行代码, 支持listview,gridView, recyclerview, 的adapter, 开发者只需要关注 item View 和 数据的关系,业务逻辑.剩下的一切交给我 将viewholder,与 ...
android listview的一个例子。使用了java的反射功能,实现自动构建adapter,不需要自己从BaseAdapter继承
baseAdapter使用详细说明 完整的注释 完美的框架、优化等 学习android列表必看
ListView的简单介绍与使用 GridView的简单介绍与使用 自定义BaseAdapter BaseAdapter的三种使用方式 ...BaseAdapter:抽象类,实际开发中我们会继承这个类并且重写相关方法,用得最多的一个Adapter!
BaseAdapter就Android应用程序中经常用到的基础数据适配器,它的主要用途是将一组数据传到像ListView、Spinner、Gallery及GridView等UI显示组件,它是继承自接口类Adapter BaseAdapter Java代码: public class ...
BaseAdapter This project is to encapsulate listview or GridView as well as Adapter. RecyclerView this project is to watch the Zhang Hongyang teacher's video and inspired by the also has a lot of older...
BaseAdapter 是一个我写的adapter的基类,感觉还是比较用,希望大家多提意见
为便于学习自定义的Adapter,本案例的界面未进行美化,功能已经实现,对于其中的getView(int position,View view ,ViewGroup vg)做了数据的填充操作。本案例功能及其简单,只涉及ListView中自定义适配器,没有对...
all-base-adapter Adapter 终结者 Adapter终结者,包含DataBinding,任意ViewGroup,Rv、Lv列表。写Adapter,有它就够了 Some base Adapters apply to any ViewGroup. Such as LinearLayout, ScrollView, and ...