Different list items’layouts
Let’s move to the “more complicated” example. How about to add separator somewhere to the list.
You should do the following:
- Override getViewTypeCount() – return how many different view layouts you have
- Override getItemViewType(int) – return correct view type id by position
- Create correct convertView (depending on view item type) in getView
当我们使用两个item布局的时候,getView()时用两种类型区分,使用不同的ViewHolder。本例item中的view都是TextView所以就使用一个ViewHolder。
convertView的缓存的分析:
getView方法:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
首先启动项目:
console打印:
I/System.out: getView 0 null type = 0
I/System.out: getView 1 null type = 0
I/System.out: getView 2 null type = 0
I/System.out: getView 3 null type = 0
I/System.out: getView 4 null type = 1
I/System.out: getView 5 null type = 0
I/System.out: getView 6 null type = 0
I/System.out: getView 7 null type = 0
滑动屏幕(滑动到19再滑动到0)观察结果:
直到第十个才出现不是null的convertView
type=0缓存了8个convertView,无论如何滑动,type=0的convertView都是相同的hashCode(出现8次)
type=1缓存了2个convertView,无论如何滑动,type=1的convertView都是相同的hashCode(出现2次)
(出现8次是因为前8次都是null)
Adapter会根据type和position得到正确的convertView传参到getView方法。
I/System.out: getView 0 null type = 0
I/System.out: getView 1 null type = 0
getView 2 null type = 0
I/System.out: getView 3 null type = 0
getView 4 null type = 1
I/System.out: getView 5 null type = 0
I/System.out: getView 6 null type = 0
getView 7 null type = 0
I/System.out: getView 8 null type = 0
I/System.out: getView 9 null type = 1
I/System.out: getView 10 android.widget.LinearLayout{ede7cb7 V.E...... ........ 0,-267-1080,3} type = 0
I/System.out: getView 11 android.widget.LinearLayout{b450c24 V.E...... ........ 0,-270-1080,0} type = 0
I/System.out: getView 12 android.widget.LinearLayout{df1538d V.E...... ........ 0,-267-1080,3} type = 0
I/System.out: getView 13 android.widget.LinearLayout{343b942 V.E...... ........ 0,-258-1080,12} type = 0
I/System.out: getView 14 android.widget.LinearLayout{1542d53 V.E...... ........ 0,-57-1080,0} type = 1
I/System.out: getView 15 android.widget.LinearLayout{7d8c690 V.E...... ........ 0,-247-1080,23} type = 0
I/System.out: getView 16 android.widget.LinearLayout{72c9b89 V.E...... ........ 0,-268-1080,2} type = 0
I/System.out: getView 17 android.widget.LinearLayout{a58278e V.E...... ........ 0,-270-1080,0} type = 0
I/System.out: getView 18 android.widget.LinearLayout{96a4baf V.E...... ........ 0,-268-1080,2} type = 0
I/System.out: getView 19 android.widget.LinearLayout{dabbbbc V.E...... ........ 0,-57-1080,0} type = 1
I/System.out: getView 11 android.widget.LinearLayout{b450c24 V.E...... ........ 0,-265-1080,5} type = 0
I/System.out: getView 10 android.widget.LinearLayout{ede7cb7 V.E...... ........ 0,-270-1080,0} type = 0
I/System.out: getView 9 android.widget.LinearLayout{dabbbbc V.E...... ........ 0,1683-1080,1740} type = 1
I/System.out: getView 8 android.widget.LinearLayout{a58278e V.E...... ........ 0,1703-1080,1973} type = 0
I/System.out: getView 7 android.widget.LinearLayout{72c9b89 V.E...... ........ 0,1670-1080,1940} type = 0
I/System.out: getView 6 android.widget.LinearLayout{7d8c690 V.E...... ........ 0,1620-1080,1890} type = 0
I/System.out: getView 5 android.widget.LinearLayout{343b942 V.E...... ........ 0,1701-1080,1971} type = 0
I/System.out: getView 4 android.widget.LinearLayout{1542d53 V.E...... ........ 0,1657-1080,1714} type = 1
I/System.out: getView 3 android.widget.LinearLayout{df1538d V.E...... ........ 0,1703-1080,1973} type = 0
I/System.out: getView 2 android.widget.LinearLayout{b450c24 V.E...... ........ 0,1651-1080,1921} type = 0
I/System.out: getView 1 android.widget.LinearLayout{ede7cb7 V.E...... ........ 0,1692-1080,1962} type = 0
I/System.out: getView 0 android.widget.LinearLayout{96a4baf V.E...... ........ 0,1674-1080,1944} type = 0
Activity源码:
package com.asyf.testlistview;
import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.TreeSet;
public class MultipleItemsList extends ListActivity {
private MyCustomAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAdapter = new MyCustomAdapter();
for (int i = 1; i < 50; i++) {
mAdapter.addItem("item " + i);
if (i % 4 == 0) {
mAdapter.addSeparatorItem("separator " + i);
}
}
setListAdapter(mAdapter);
}
private class MyCustomAdapter extends BaseAdapter {
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
private ArrayList<String> mData = new ArrayList<String>();
private LayoutInflater mInflater;
private TreeSet<Integer> mSeparatorsSet = new TreeSet<Integer>();
public MyCustomAdapter() {
mInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void addItem(final String item) {
mData.add(item);
notifyDataSetChanged();
}
public void addSeparatorItem(final String item) {
mData.add(item);
// save separator position
mSeparatorsSet.add(mData.size() - 1);
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
@Override
public int getViewTypeCount() {
return TYPE_MAX_COUNT;
}
@Override
public int getCount() {
return mData.size();
}
@Override
public String getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item2, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(mData.get(position));
return convertView;
}
}
public static class ViewHolder {
public TextView textView;
}
}
项目源码下载 https://gitee.com/373616511/TestListView.git