Merge changes I6e3f4da2,I8acfbd1a into nyc-dev
* changes: Fully detach unused scrap views Remove detached headers
This commit is contained in:
@@ -2322,7 +2322,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
*
|
||||
* @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.
|
||||
* the returned view was taken from the "temporary detached" scrap heap, false if
|
||||
* otherwise.
|
||||
*
|
||||
* @return A view displaying the data associated with the specified position
|
||||
*/
|
||||
@@ -2362,10 +2363,18 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
// Failed to re-bind the data, return scrap to the heap.
|
||||
mRecycler.addScrapView(scrapView, position);
|
||||
} else {
|
||||
isScrap[0] = true;
|
||||
if (child.isTemporarilyDetached()) {
|
||||
isScrap[0] = true;
|
||||
|
||||
// Finish the temporary detach started in addScrapView().
|
||||
child.dispatchFinishTemporaryDetach();
|
||||
} else {
|
||||
// we set isScrap to "true" only if the view is temporarily detached.
|
||||
// if the view is fully detached, it is as good as a view created by the
|
||||
// adapter
|
||||
isScrap[0] = false;
|
||||
}
|
||||
|
||||
// Finish the temporary detach started in addScrapView().
|
||||
child.dispatchFinishTemporaryDetach();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5152,6 +5161,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
fillGap(down);
|
||||
}
|
||||
|
||||
mRecycler.fullyDetachScrapViews();
|
||||
if (!inTouchMode && mSelectedPosition != INVALID_POSITION) {
|
||||
final int childIndex = mSelectedPosition - mFirstPosition;
|
||||
if (childIndex >= 0 && childIndex < getChildCount()) {
|
||||
@@ -6861,8 +6871,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
scrapViews = mScrapViews[whichScrap];
|
||||
}
|
||||
|
||||
victim.dispatchStartTemporaryDetach();
|
||||
lp.scrappedFromPosition = mFirstActivePosition + i;
|
||||
removeDetachedView(victim, false);
|
||||
scrapViews.add(victim);
|
||||
|
||||
if (hasListener) {
|
||||
@@ -6871,10 +6881,28 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pruneScrapViews();
|
||||
}
|
||||
|
||||
/**
|
||||
* At the end of a layout pass, all temp detached views should either be re-attached or
|
||||
* completely detached. This method ensures that any remaining view in the scrap list is
|
||||
* fully detached.
|
||||
*/
|
||||
void fullyDetachScrapViews() {
|
||||
final int viewTypeCount = mViewTypeCount;
|
||||
final ArrayList<View>[] scrapViews = mScrapViews;
|
||||
for (int i = 0; i < viewTypeCount; ++i) {
|
||||
final ArrayList<View> scrapPile = scrapViews[i];
|
||||
for (int j = scrapPile.size() - 1; j >= 0; j--) {
|
||||
final View view = scrapPile.get(j);
|
||||
if (view.isTemporarilyDetached()) {
|
||||
removeDetachedView(view, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that the size of mScrapViews does not exceed the size of
|
||||
* mActiveViews, which can happen if an adapter does not recycle its
|
||||
@@ -6888,10 +6916,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
||||
for (int i = 0; i < viewTypeCount; ++i) {
|
||||
final ArrayList<View> scrapPile = scrapViews[i];
|
||||
int size = scrapPile.size();
|
||||
final int extras = size - maxViews;
|
||||
size--;
|
||||
for (int j = 0; j < extras; j++) {
|
||||
removeDetachedView(scrapPile.remove(size--), false);
|
||||
while (size > maxViews) {
|
||||
scrapPile.remove(--size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ import android.view.accessibility.AccessibilityNodeProvider;
|
||||
import android.widget.RemoteViews.RemoteView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* Implementation Notes:
|
||||
@@ -1763,6 +1764,10 @@ public class ListView extends AbsListView {
|
||||
// Flush any cached views that did not get reused above
|
||||
recycleBin.scrapActiveViews();
|
||||
|
||||
// remove any header/footer that has been temp detached and not re-attached
|
||||
removeUnusedFixedViews(mHeaderViewInfos);
|
||||
removeUnusedFixedViews(mFooterViewInfos);
|
||||
|
||||
if (sel != null) {
|
||||
// The current selected item should get focus if items are
|
||||
// focusable.
|
||||
@@ -1879,6 +1884,36 @@ public class ListView extends AbsListView {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean trackMotionScroll(int deltaY, int incrementalDeltaY) {
|
||||
final boolean result = super.trackMotionScroll(deltaY, incrementalDeltaY);
|
||||
removeUnusedFixedViews(mHeaderViewInfos);
|
||||
removeUnusedFixedViews(mFooterViewInfos);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Header and Footer views are not scrapped / recycled like other views but they are still
|
||||
* detached from the ViewGroup. After a layout operation, call this method to remove such views.
|
||||
*
|
||||
* @param infoList The info list to be traversed
|
||||
*/
|
||||
private void removeUnusedFixedViews(@Nullable List<FixedViewInfo> infoList) {
|
||||
if (infoList == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = infoList.size() - 1; i >= 0; i--) {
|
||||
final FixedViewInfo fixedViewInfo = infoList.get(i);
|
||||
final View view = fixedViewInfo.view;
|
||||
final LayoutParams lp = (LayoutParams) view.getLayoutParams();
|
||||
if (view.getParent() == null && lp != null && lp.recycledHeaderFooter) {
|
||||
removeDetachedView(view, false);
|
||||
lp.recycledHeaderFooter = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param child a direct child of this list.
|
||||
* @return Whether child is a header or footer view.
|
||||
@@ -3179,6 +3214,9 @@ public class ListView extends AbsListView {
|
||||
last = getChildAt(--lastIndex);
|
||||
}
|
||||
}
|
||||
recycleBin.fullyDetachScrapViews();
|
||||
removeUnusedFixedViews(mHeaderViewInfos);
|
||||
removeUnusedFixedViews(mFooterViewInfos);
|
||||
}
|
||||
|
||||
private View addViewAbove(View theView, int position) {
|
||||
|
||||
Reference in New Issue
Block a user