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:


  1. Override getViewTypeCount() – return how many different view layouts you have
  2. Override getItemViewType(int) – return correct view type id by position
  3. 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;
}


首先启动项目:

ListView使用多个item布局的用法及分析,Adapter的getView方法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​