复用分析
**1. 在AbListView中 **
/**
* The data set used to store unused views that should be reused during the next layout
* to avoid creating new ones
*/
final RecycleBin mRecycler = new RecycleBin();
RecycleBin包含了两个级别的存储,ActiveViews和ScrapViews,ActiveViews存储的是第一次显示在屏幕上的View;所有的ActiveViews最终都会被移到ScrapViews,ScrapViews存储的是有可能被adapter复用的View。
**2. 在ListView的LayoutChildren 中 **
@Override
protected void layoutChildren()
{
if (dataChanged)
{
for (int i = 0; i < childCount; i++)
{
recycleBin.addScrapView(getChildAt(i));
}
} else
{
recycleBin.fillActiveViews(childCount, firstPosition);
}
....
}
可以看出,如果数据发生变化则把当前的ItemView放入ScrapViews中,否则把当前显示的ItemView放入ActiveViews中。
3. 那么咱们关键的getView方法到底是在哪调用呢
在AbsListView中我们看obtainView中的方法:
/**
* Get a view and have it show the data associated with the specified
* position. This is called when we have already discovered that the view is
* not available for reuse in the recycle bin. The only choices left are
* converting an old view or making a new one.
*
* @param position The position to display
* @param isScrap Array of at least 1 boolean, the first entry will become true if
* the returned view was taken from the scrap heap, false if otherwise.
*
* @return A view displaying the data associated with the specified position
*/
View obtainView(int position, boolean[] isScrap)
{
final View scrapView = mRecycler.getScrapView(position);
final View child = mAdapter.getView(position, scrapView, this);
if (scrapView != null) {
if (child != scrapView) {
// Failed to re-bind the data, return scrap to the heap.
mRecycler.addScrapView(scrapView, position);
} else {
isScrap[0] = true;
child.dispatchFinishTemporaryDetach();
}
}
return child;
}
可以看到,这个方法就是返回当前一个布局用户当前Item的显示,首先根据position去ScrapView中找,找到后调用我们的getView,此时getView里面的convertView!=null了,然后getView如果返回的View发生变化,缓存下来,否则convertView==null了。