先来讲解几个知识点:
1 BaseAdapter:
任意的ListView都需要一个适配器,这里就拿自定义的适配器来说,比如我们自己定义了一个适配器MyAdapter,然后让这个适配器继承了BaseAdapter,即MyAdapter extends BaseAdapter,那么我们需要重写他的四个方法,
getCount(),getItem(int position),getItemId(int position)以及getView(int position,View convertView,ViewGroup parent);其实这四个方法都是在一个叫做Adapter的接口中定义的,说白了结构如下
interface Adapter:这里面包含了以上四个方法;
interface ListAdapter extends Adapter: ListView的适配器,里面定义了两个属性,一般不用;
interface SpinnerAdapter extends Adapter:这里面有一个getDropDownView(int position,View convertView,ViewGroup parent)方法,用于给Spinner设置下拉点击的视图;
abstract class BaseAdapter implements ListAdapter,SpinnerAdapter:这就是我们常见的BaseAdapter,它里面又定义了两个方法getViewTypeCount()和getItemViewType(int position),这两个方法在ListView加载不同的布局时会用到,这里面又重写了一个方法getDropDownView(),里面调用了Adapter里面的getView();
到这里我们可以明白:我们的定义的适配器MyAdapter里面的重写四个方法都是在Adapter这个接口里面的定义的,完全是自己重写的,那么getView(int position, View convertView,ViewGroup parent)这里面的convertView和parent有什么用呢?
第一:convertView参数,其实是一个包含了item的View,他里面可以包含很多个item,当然这些item种类是不同的,也就是说每种item只有一个,比如现在ListView总共显示了n种item,那么convertView里面最多可以包含n个item,并且都不相同,当ListView向上滑动的时候,就会从convertView里面取出(getTag())需要的item来显示,如果没有此类的item,就会创建一个,然后把它添加(setTag())到convertView里面以备下次需要;
第二:parent 参数,这个参数有特殊的意义,必须配合LayoutInflater的inflate(int resource,ViewGroup root,Boolean attachToRoot)来说明;下面来说明一下
LayoutInflater的inflate函数,
2 LayoutInflater的inflate函数
首先LayoutInflaer里面定义了四个inflate函数:
两个参数的:
(1)View inflate(int resource,ViewGroup root);
(2)View inflate(XmlPullParser parser,ViewGroup root);
三个参数的:
(3)View inflate(int resource,ViewGroup root,boolean attachToRoot);
(4)View inflate(XmlPullParser parser,ViewGroup root,boolean attachToRoot);
以上四个函数中(1)调用了(2),(2)和(3)均调用了(4),所以说,所有的实现都是在(4)中实现的;那么我们来看一下(4):
View inflate(XmlPullParser parser,ViewGroup root,boolean attachToRoot):
第一个参数就是用来解析我们的xml文件从而得到有关布局的信息,xml文件我们在调用inflate(R.layout.xxx,...,...)时给出了,就是R.layout.xxx,解析后我们得到了布局的信息,也就是一个AttributeSet对象,用这个对象我们可以初始化ViewGroup.LayoutParams这个类,然后可以用来设置我们的布局(R.layout.xxx)的属性;
当我们调用inflate(R.layout.xxx,null)或者inflate(R.layout.xxx,parent,false)时:
返回的是我们的R.Layout.xxx对象,然后用getView()里面的第二个参数parent构造了一个ViewHolder.LayoutParams对象,用这个对象设置了R.layout.xxx的大小和尺寸,所以相当于是把R.layout.xxx填充到parent里面然后返回这个parent;
当我们调用inflate(R.layout.xxx,parent,true)时:
实际上是将R.layout.xxx添加到parent中然后返回这个parent