Loading core/java/android/widget/AbsListView.java +92 −73 Original line number Diff line number Diff line Loading @@ -2284,26 +2284,28 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te Trace.traceBegin(Trace.TRACE_TAG_VIEW, "obtainView"); isScrap[0] = false; View scrapView; scrapView = mRecycler.getTransientStateView(position); if (scrapView == null) { scrapView = mRecycler.getScrapView(position); // Check whether we have a transient state view. Attempt to re-bind the // data and discard the view if we fail. final View transientView = mRecycler.getTransientStateView(position); if (transientView != null) { final View updatedView = mAdapter.getView(position, transientView, this); if (updatedView != transientView) { // Failed to re-bind the data, scrap the obtained view. mRecycler.addScrapView(updatedView, position); } View child; if (scrapView != null) { child = mAdapter.getView(position, scrapView, this); if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); // Scrap view implies temporary detachment. isScrap[0] = true; return transientView; } 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); if (mCacheColorHint != 0) { child.setDrawingCacheBackgroundColor(mCacheColorHint); } } else { isScrap[0] = true; Loading @@ -2315,16 +2317,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te child.dispatchFinishTemporaryDetach(); } } else { child = mAdapter.getView(position, null, this); if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } if (mCacheColorHint != 0) { child.setDrawingCacheBackgroundColor(mCacheColorHint); } if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } if (mAdapterHasStableIds) { Loading Loading @@ -6618,12 +6618,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } if (mTransientStateViews != null) { mTransientStateViews.clear(); } if (mTransientStateViewsById != null) { mTransientStateViewsById.clear(); } clearTransientStateViews(); } /** Loading Loading @@ -6690,14 +6686,26 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } /** * Dump any currently saved views with transient state. * Dumps and fully detaches any currently saved views with transient * state. */ void clearTransientStateViews() { if (mTransientStateViews != null) { mTransientStateViews.clear(); final SparseArray<View> viewsByPos = mTransientStateViews; if (viewsByPos != null) { final int N = viewsByPos.size(); for (int i = 0; i < N; i++) { removeDetachedView(viewsByPos.valueAt(i), false); } if (mTransientStateViewsById != null) { mTransientStateViewsById.clear(); viewsByPos.clear(); } final LongSparseArray<View> viewsById = mTransientStateViewsById; if (viewsById != null) { final int N = viewsById.size(); for (int i = 0; i < N; i++) { removeDetachedView(viewsById.valueAt(i), false); } viewsById.clear(); } } Loading Loading @@ -6822,37 +6830,40 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (victim != null) { final AbsListView.LayoutParams lp = (AbsListView.LayoutParams) victim.getLayoutParams(); int whichScrap = lp.viewType; final int whichScrap = lp.viewType; activeViews[i] = null; final boolean scrapHasTransientState = victim.hasTransientState(); if (!shouldRecycleViewType(whichScrap) || scrapHasTransientState) { // Do not move views that should be ignored if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER && scrapHasTransientState) { removeDetachedView(victim, false); } if (scrapHasTransientState) { if (victim.hasTransientState()) { // Store views with transient state for later use. victim.dispatchStartTemporaryDetach(); if (mAdapter != null && mAdapterHasStableIds) { if (mTransientStateViewsById == null) { mTransientStateViewsById = new LongSparseArray<View>(); } long id = mAdapter.getItemId(mFirstActivePosition + i); mTransientStateViewsById.put(id, victim); } else { } else if (!mDataChanged) { if (mTransientStateViews == null) { mTransientStateViews = new SparseArray<View>(); } mTransientStateViews.put(mFirstActivePosition + i, victim); } else if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { // The data has changed, we can't keep this view. removeDetachedView(victim, false); } } else if (!shouldRecycleViewType(whichScrap)) { // Discard non-recyclable views except headers/footers. if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { removeDetachedView(victim, false); } continue; } } else { // Store everything else on the appropriate scrap heap. if (multipleScraps) { scrapViews = mScrapViews[whichScrap]; } victim.dispatchStartTemporaryDetach(); lp.scrappedFromPosition = mFirstActivePosition + i; scrapViews.add(victim); Loading @@ -6863,13 +6874,16 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } } pruneScrapViews(); } /** * Makes sure that the size of mScrapViews does not exceed the size of mActiveViews. * (This can happen if an adapter does not recycle its views). * Makes sure that the size of mScrapViews does not exceed the size of * mActiveViews, which can happen if an adapter does not recycle its * views. Removes cached transient state views that no longer have * transient state. */ private void pruneScrapViews() { final int maxViews = mActiveViews.length; Loading @@ -6885,20 +6899,25 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } if (mTransientStateViews != null) { for (int i = 0; i < mTransientStateViews.size(); i++) { final View v = mTransientStateViews.valueAt(i); final SparseArray<View> transViewsByPos = mTransientStateViews; if (transViewsByPos != null) { for (int i = 0; i < transViewsByPos.size(); i++) { final View v = transViewsByPos.valueAt(i); if (!v.hasTransientState()) { mTransientStateViews.removeAt(i); removeDetachedView(v, false); transViewsByPos.removeAt(i); i--; } } } if (mTransientStateViewsById != null) { for (int i = 0; i < mTransientStateViewsById.size(); i++) { final View v = mTransientStateViewsById.valueAt(i); final LongSparseArray<View> transViewsById = mTransientStateViewsById; if (transViewsById != null) { for (int i = 0; i < transViewsById.size(); i++) { final View v = transViewsById.valueAt(i); if (!v.hasTransientState()) { mTransientStateViewsById.removeAt(i); removeDetachedView(v, false); transViewsById.removeAt(i); i--; } } Loading Loading
core/java/android/widget/AbsListView.java +92 −73 Original line number Diff line number Diff line Loading @@ -2284,26 +2284,28 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te Trace.traceBegin(Trace.TRACE_TAG_VIEW, "obtainView"); isScrap[0] = false; View scrapView; scrapView = mRecycler.getTransientStateView(position); if (scrapView == null) { scrapView = mRecycler.getScrapView(position); // Check whether we have a transient state view. Attempt to re-bind the // data and discard the view if we fail. final View transientView = mRecycler.getTransientStateView(position); if (transientView != null) { final View updatedView = mAdapter.getView(position, transientView, this); if (updatedView != transientView) { // Failed to re-bind the data, scrap the obtained view. mRecycler.addScrapView(updatedView, position); } View child; if (scrapView != null) { child = mAdapter.getView(position, scrapView, this); if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); // Scrap view implies temporary detachment. isScrap[0] = true; return transientView; } 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); if (mCacheColorHint != 0) { child.setDrawingCacheBackgroundColor(mCacheColorHint); } } else { isScrap[0] = true; Loading @@ -2315,16 +2317,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te child.dispatchFinishTemporaryDetach(); } } else { child = mAdapter.getView(position, null, this); if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } if (mCacheColorHint != 0) { child.setDrawingCacheBackgroundColor(mCacheColorHint); } if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } if (mAdapterHasStableIds) { Loading Loading @@ -6618,12 +6618,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } if (mTransientStateViews != null) { mTransientStateViews.clear(); } if (mTransientStateViewsById != null) { mTransientStateViewsById.clear(); } clearTransientStateViews(); } /** Loading Loading @@ -6690,14 +6686,26 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } /** * Dump any currently saved views with transient state. * Dumps and fully detaches any currently saved views with transient * state. */ void clearTransientStateViews() { if (mTransientStateViews != null) { mTransientStateViews.clear(); final SparseArray<View> viewsByPos = mTransientStateViews; if (viewsByPos != null) { final int N = viewsByPos.size(); for (int i = 0; i < N; i++) { removeDetachedView(viewsByPos.valueAt(i), false); } if (mTransientStateViewsById != null) { mTransientStateViewsById.clear(); viewsByPos.clear(); } final LongSparseArray<View> viewsById = mTransientStateViewsById; if (viewsById != null) { final int N = viewsById.size(); for (int i = 0; i < N; i++) { removeDetachedView(viewsById.valueAt(i), false); } viewsById.clear(); } } Loading Loading @@ -6822,37 +6830,40 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (victim != null) { final AbsListView.LayoutParams lp = (AbsListView.LayoutParams) victim.getLayoutParams(); int whichScrap = lp.viewType; final int whichScrap = lp.viewType; activeViews[i] = null; final boolean scrapHasTransientState = victim.hasTransientState(); if (!shouldRecycleViewType(whichScrap) || scrapHasTransientState) { // Do not move views that should be ignored if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER && scrapHasTransientState) { removeDetachedView(victim, false); } if (scrapHasTransientState) { if (victim.hasTransientState()) { // Store views with transient state for later use. victim.dispatchStartTemporaryDetach(); if (mAdapter != null && mAdapterHasStableIds) { if (mTransientStateViewsById == null) { mTransientStateViewsById = new LongSparseArray<View>(); } long id = mAdapter.getItemId(mFirstActivePosition + i); mTransientStateViewsById.put(id, victim); } else { } else if (!mDataChanged) { if (mTransientStateViews == null) { mTransientStateViews = new SparseArray<View>(); } mTransientStateViews.put(mFirstActivePosition + i, victim); } else if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { // The data has changed, we can't keep this view. removeDetachedView(victim, false); } } else if (!shouldRecycleViewType(whichScrap)) { // Discard non-recyclable views except headers/footers. if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { removeDetachedView(victim, false); } continue; } } else { // Store everything else on the appropriate scrap heap. if (multipleScraps) { scrapViews = mScrapViews[whichScrap]; } victim.dispatchStartTemporaryDetach(); lp.scrappedFromPosition = mFirstActivePosition + i; scrapViews.add(victim); Loading @@ -6863,13 +6874,16 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } } pruneScrapViews(); } /** * Makes sure that the size of mScrapViews does not exceed the size of mActiveViews. * (This can happen if an adapter does not recycle its views). * Makes sure that the size of mScrapViews does not exceed the size of * mActiveViews, which can happen if an adapter does not recycle its * views. Removes cached transient state views that no longer have * transient state. */ private void pruneScrapViews() { final int maxViews = mActiveViews.length; Loading @@ -6885,20 +6899,25 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } if (mTransientStateViews != null) { for (int i = 0; i < mTransientStateViews.size(); i++) { final View v = mTransientStateViews.valueAt(i); final SparseArray<View> transViewsByPos = mTransientStateViews; if (transViewsByPos != null) { for (int i = 0; i < transViewsByPos.size(); i++) { final View v = transViewsByPos.valueAt(i); if (!v.hasTransientState()) { mTransientStateViews.removeAt(i); removeDetachedView(v, false); transViewsByPos.removeAt(i); i--; } } } if (mTransientStateViewsById != null) { for (int i = 0; i < mTransientStateViewsById.size(); i++) { final View v = mTransientStateViewsById.valueAt(i); final LongSparseArray<View> transViewsById = mTransientStateViewsById; if (transViewsById != null) { for (int i = 0; i < transViewsById.size(); i++) { final View v = transViewsById.valueAt(i); if (!v.hasTransientState()) { mTransientStateViewsById.removeAt(i); removeDetachedView(v, false); transViewsById.removeAt(i); i--; } } Loading