listView的convertView复用机制
1、convertView的数量=屏幕item数量+item样式数量*1;
2、listView对convertView回收,根据getItemType(position)获取item样式数量,然后创建一个数组,元素为list集合,数组长度刚好为Item样式数量(这也是为什么item样式只能从零开始定义的原因);
3、convertView复用时,会先调用getItemType(position)来确定当前item需要的样式,再从对用数组的元素即集合中获取对应样式来装配;
源码:
public void setViewTypeCount(int viewTypeCount) {
if (viewTypeCount < 1) {
throw new IllegalArgumentException("Can't have a viewTypeCount < 1");
}
//noinspection unchecked
ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount];
for (int i = 0; i < viewTypeCount; i++) {
scrapViews[i] = new ArrayList<View>();
}
mViewTypeCount = viewTypeCount;
mCurrentScrap = scrapViews[0];
mScrapViews = scrapViews;
}
/**
* @return A view from the ScrapViews collection. These are unordered.
*/
View getScrapView(int position) {
if (mViewTypeCount == 1) {
return retrieveFromScrap(mCurrentScrap, position);
} else {
int whichScrap = mAdapter.getItemViewType(position);
if (whichScrap >= 0 && whichScrap < mScrapViews.length) {
return retrieveFromScrap(mScrapViews[whichScrap], position);
}
}
return null;
}
/**
* Puts a view into the list of scrap views.
* <p>
* If the list data hasn't changed or the adapter has stable IDs, views
* with transient state will be preserved for later retrieval.
*
* @param scrap The view to add
* @param position The view's position within its parent
*/
void addScrapView(View scrap, int position) {
final AbsListView.LayoutParams lp = (AbsListView.LayoutParams) scrap.getLayoutParams();
if (lp == null) {
return;
}
lp.scrappedFromPosition = position;
// Remove but don't scrap header or footer views, or views that
// should otherwise not be recycled.
final int viewType = lp.viewType;
if (!shouldRecycleViewType(viewType)) {
return;
}
scrap.dispatchStartTemporaryDetach();
// Don't scrap views that have transient state.
final boolean scrapHasTransientState = scrap.hasTransientState();
if (scrapHasTransientState) {
if (mAdapter != null && mAdapterHasStableIds) {
// If the adapter has stable IDs, we can reuse the view for
// the same data.
if (mTransientStateViewsById == null) {
mTransientStateViewsById = new LongSparseArray<View>();
}
mTransientStateViewsById.put(lp.itemId, scrap);
} else if (!mDataChanged) {
// If the data hasn't changed, we can reuse the views at
// their old positions.
if (mTransientStateViews == null) {
mTransientStateViews = new SparseArray<View>();
}
mTransientStateViews.put(position, scrap);
} else {
// Otherwise, we'll have to remove the view and start over.
if (mSkippedScrap == null) {
mSkippedScrap = new ArrayList<View>();
}
mSkippedScrap.add(scrap);
}
} else {
if (mViewTypeCount == 1) {
mCurrentScrap.add(scrap);
} else {
mScrapViews[viewType].add(scrap);
}
// Clear any system-managed transient state.
if (scrap.isAccessibilityFocused()) {
scrap.clearAccessibilityFocus();
}
scrap.setAccessibilityDelegate(null);
if (mRecyclerListener != null) {
mRecyclerListener.onMovedToScrapHeap(scrap);
}
}
}
Demon:
package cn.snow.learning.multystylelistview;
import java.util.ArrayList;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class MainActivity extends Activity
{
public static final int IMAGEVIEW = 0;
public static final int TEXTVIEW = 1;
private ArrayList<String> mData;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.listView);
mData = getData();
listView.setAdapter(new MyBaseAdapter());
}
private ArrayList<String> getData()
{
ArrayList<String> data = new ArrayList<String>();
for (int i = 0; i < 50; i++)
{
data.add("测试数据" + i);
}
return data;
}
class MyBaseAdapter extends BaseAdapter
{
@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 int getViewTypeCount()
{
return 2;
}
@Override
public int getItemViewType(int position)
{
if (position % 10 == 0)
{
return IMAGEVIEW;
}
return TEXTVIEW;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder = null;
int type = getItemViewType(position);
if (convertView == null)
{
viewHolder = new ViewHolder();
switch (type)
{
case TEXTVIEW:
viewHolder.textView = new TextView(getBaseContext());
convertView = viewHolder.textView;
break;
case IMAGEVIEW:
ImageView imageView = new ImageView(getBaseContext());
imageView.setImageResource(R.drawable.ic_launcher);
/*
* viewHolder.textView = new TextView(getBaseContext());
* viewHolder.textView.setBackgroundColor(Color.BLUE);
*/
convertView = imageView;
break;
default:
break;
}
convertView.setTag(viewHolder);
Log.i("初始化:" + position, convertView.toString());
} else
{
Log.i("复用:" + position, convertView.toString());
viewHolder = (ViewHolder) convertView.getTag();
}
if (type == TEXTVIEW)
{
viewHolder.textView.setText(mData.get(position));
}
return convertView;
}
public class ViewHolder
{
public TextView textView;
}
}
}