本文为摘抄 + 自己的理解 摘自:http://haking.iteye.com/blog/1147404
一、ListView的关键在与Adapter.getView方法:
public View getView(int position, View convertView, ViewGroup parent);
该方法用于获取指定位置要显示的View。需要显示一个View时就该方法被触发一次。ListView的每个Item都通过getView返回并显示。
其中的convertView是Android所做的缓存机制,Android提供了Recycler,将没有正在显示的item放进RecycleBin,然后在显示新视图时从RecycleBin中复用这个view。
Recycler的工作原理:
一个屏幕最多只能看到10个item,当第一个item滚出屏幕时,该item的view进入RecycleBin中,第11个item(新的item)要出现之前,触发getView方法,从回收站RecycleBin中重用这个view,而不必重新创建一个view。
通过重用convertView,可以避免每次都创建新的view,节省内存且优化ListView的滑动流畅度。
我们用Android提供的APIDemos来验证这个过程:
- public View getView(int position, View convertView, ViewGroup parent) {
- // A ViewHolder keeps references to children views to avoid unneccessary calls
- // to findViewById() on each row.
- ViewHolder holder;
- // When convertView is not null, we can reuse it directly, there is no need
- // to reinflate it. We only inflate a new View when the convertView supplied
- // by ListView is null.
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.list_item_icon_text, null);
- Log.v("tag", "positon " + position + " convertView is null, " + "new: " + convertView);
- // Creates a ViewHolder and store references to the two children views
- // we want to bind data to.
- holder = new ViewHolder();
- holder.text = (TextView) convertView.findViewById(R.id.text);
- holder.icon = (ImageView) convertView.findViewById(R.id.icon);
- convertView.setTag(holder);
- } else {
- // Get the ViewHolder back to get fast access to the TextView
- // and the ImageView.
- holder = (ViewHolder) convertView.getTag();
- Log.v("tag", "positon " + position + " convertView is not null, " + convertView);
- }
- // Bind the data efficiently with the holder.
- holder.text.setText(DATA[position]);
- holder.icon.setImageBitmap((position & 1) == 1 ? mIcon1 : mIcon2);
- return convertView;
- }
- static class ViewHolder {
- TextView text;
- ImageView icon;
- }
4. getItemViewType(int)与getItemViewType(int)
getItemViewType(int) can not return int value larger than getViewTypeCount().
Otherwise you will get java.lang.ArrayIndexOutOfBoundsException at android.widget.AbsListView$RecycleBin.addScrapView(AbsListView.java:3523)
ListView会根据不同的ViewType返回相应type的convertView.
一般写法:
getView() {
switch (getItemViewType(position)) {
case type1:
if(convertView == null) {
} else {
}
break;
case type2:
default:
if(convertView == null) {
} else {
}
break;
}
return convertView;
}
getItemViewType(int position) {
// 根据场景,一般有:
// 1. 不同的item type对应的position是固定的,那么ListView的data可以分别存放
// 2. 不同的item type对应的position是不固定的,那么可以把ListView的data统一放在List<Object>中,
// 然后使用instanceof来判断Object的类型进而区分position对应的view type.
}