Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cac41c96 authored by Yigit Boyar's avatar Yigit Boyar Committed by android-build-merger
Browse files

Merge changes I6e3f4da2,I8acfbd1a into nyc-dev am: 1a97cbd4

am: c8777a83

* commit 'c8777a83':
  Fully detach unused scrap views
  Remove detached headers

Change-Id: I3d58765bcb7264892f0280b37b702e3dbbccdfd4
parents c614d4ed c8777a83
Loading
Loading
Loading
Loading
+36 −10
Original line number Diff line number Diff line
@@ -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 {
                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;
                }

            }
        }

@@ -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);
                }
            }

+38 −0
Original line number Diff line number Diff line
@@ -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) {