Merge "DO NOT MERGE Ensure transient state views are temporarily detached" into klp-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
6a5b7c6ffb
@@ -2228,26 +2228,28 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "obtainView");
|
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "obtainView");
|
||||||
|
|
||||||
isScrap[0] = false;
|
isScrap[0] = false;
|
||||||
View scrapView;
|
|
||||||
|
|
||||||
scrapView = mRecycler.getTransientStateView(position);
|
// Check whether we have a transient state view. Attempt to re-bind the
|
||||||
if (scrapView == null) {
|
// data and discard the view if we fail.
|
||||||
scrapView = mRecycler.getScrapView(position);
|
final View transientView = mRecycler.getTransientStateView(position);
|
||||||
}
|
if (transientView != null) {
|
||||||
|
final View updatedView = mAdapter.getView(position, transientView, this);
|
||||||
View child;
|
if (updatedView != transientView) {
|
||||||
if (scrapView != null) {
|
// Failed to re-bind the data, scrap the obtained view.
|
||||||
child = mAdapter.getView(position, scrapView, this);
|
mRecycler.addScrapView(updatedView, position);
|
||||||
|
|
||||||
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) {
|
if (child != scrapView) {
|
||||||
|
// Failed to re-bind the data, return scrap to the heap.
|
||||||
mRecycler.addScrapView(scrapView, position);
|
mRecycler.addScrapView(scrapView, position);
|
||||||
if (mCacheColorHint != 0) {
|
|
||||||
child.setDrawingCacheBackgroundColor(mCacheColorHint);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
isScrap[0] = true;
|
isScrap[0] = true;
|
||||||
|
|
||||||
@@ -2259,16 +2261,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
|
|
||||||
child.dispatchFinishTemporaryDetach();
|
child.dispatchFinishTemporaryDetach();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
child = mAdapter.getView(position, null, this);
|
|
||||||
|
|
||||||
if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
|
if (mCacheColorHint != 0) {
|
||||||
child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
|
child.setDrawingCacheBackgroundColor(mCacheColorHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCacheColorHint != 0) {
|
if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
|
||||||
child.setDrawingCacheBackgroundColor(mCacheColorHint);
|
child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAdapterHasStableIds) {
|
if (mAdapterHasStableIds) {
|
||||||
@@ -6562,12 +6562,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mTransientStateViews != null) {
|
|
||||||
mTransientStateViews.clear();
|
clearTransientStateViews();
|
||||||
}
|
|
||||||
if (mTransientStateViewsById != null) {
|
|
||||||
mTransientStateViewsById.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -6634,14 +6630,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() {
|
void clearTransientStateViews() {
|
||||||
if (mTransientStateViews != null) {
|
final SparseArray<View> viewsByPos = mTransientStateViews;
|
||||||
mTransientStateViews.clear();
|
if (viewsByPos != null) {
|
||||||
|
final int N = viewsByPos.size();
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
removeDetachedView(viewsByPos.valueAt(i), false);
|
||||||
|
}
|
||||||
|
viewsByPos.clear();
|
||||||
}
|
}
|
||||||
if (mTransientStateViewsById != null) {
|
|
||||||
mTransientStateViewsById.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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6766,44 +6774,48 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
if (victim != null) {
|
if (victim != null) {
|
||||||
final AbsListView.LayoutParams lp
|
final AbsListView.LayoutParams lp
|
||||||
= (AbsListView.LayoutParams) victim.getLayoutParams();
|
= (AbsListView.LayoutParams) victim.getLayoutParams();
|
||||||
int whichScrap = lp.viewType;
|
final int whichScrap = lp.viewType;
|
||||||
|
|
||||||
activeViews[i] = null;
|
activeViews[i] = null;
|
||||||
|
|
||||||
final boolean scrapHasTransientState = victim.hasTransientState();
|
if (victim.hasTransientState()) {
|
||||||
if (!shouldRecycleViewType(whichScrap) || scrapHasTransientState) {
|
// Store views with transient state for later use.
|
||||||
// Do not move views that should be ignored
|
victim.dispatchStartTemporaryDetach();
|
||||||
if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER &&
|
|
||||||
scrapHasTransientState) {
|
if (mAdapter != null && mAdapterHasStableIds) {
|
||||||
|
if (mTransientStateViewsById == null) {
|
||||||
|
mTransientStateViewsById = new LongSparseArray<View>();
|
||||||
|
}
|
||||||
|
long id = mAdapter.getItemId(mFirstActivePosition + i);
|
||||||
|
mTransientStateViewsById.put(id, victim);
|
||||||
|
} 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);
|
removeDetachedView(victim, false);
|
||||||
}
|
}
|
||||||
if (scrapHasTransientState) {
|
} else if (!shouldRecycleViewType(whichScrap)) {
|
||||||
if (mAdapter != null && mAdapterHasStableIds) {
|
// Discard non-recyclable views except headers/footers.
|
||||||
if (mTransientStateViewsById == null) {
|
if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
|
||||||
mTransientStateViewsById = new LongSparseArray<View>();
|
removeDetachedView(victim, false);
|
||||||
}
|
}
|
||||||
long id = mAdapter.getItemId(mFirstActivePosition + i);
|
} else {
|
||||||
mTransientStateViewsById.put(id, victim);
|
// Store everything else on the appropriate scrap heap.
|
||||||
} else {
|
if (multipleScraps) {
|
||||||
if (mTransientStateViews == null) {
|
scrapViews = mScrapViews[whichScrap];
|
||||||
mTransientStateViews = new SparseArray<View>();
|
|
||||||
}
|
|
||||||
mTransientStateViews.put(mFirstActivePosition + i, victim);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (multipleScraps) {
|
victim.dispatchStartTemporaryDetach();
|
||||||
scrapViews = mScrapViews[whichScrap];
|
lp.scrappedFromPosition = mFirstActivePosition + i;
|
||||||
}
|
scrapViews.add(victim);
|
||||||
victim.dispatchStartTemporaryDetach();
|
|
||||||
lp.scrappedFromPosition = mFirstActivePosition + i;
|
|
||||||
scrapViews.add(victim);
|
|
||||||
|
|
||||||
victim.setAccessibilityDelegate(null);
|
victim.setAccessibilityDelegate(null);
|
||||||
if (hasListener) {
|
if (hasListener) {
|
||||||
mRecyclerListener.onMovedToScrapHeap(victim);
|
mRecyclerListener.onMovedToScrapHeap(victim);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6812,8 +6824,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes sure that the size of mScrapViews does not exceed the size of mActiveViews.
|
* Makes sure that the size of mScrapViews does not exceed the size of
|
||||||
* (This can happen if an adapter does not recycle its views).
|
* 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() {
|
private void pruneScrapViews() {
|
||||||
final int maxViews = mActiveViews.length;
|
final int maxViews = mActiveViews.length;
|
||||||
@@ -6829,20 +6843,25 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mTransientStateViews != null) {
|
final SparseArray<View> transViewsByPos = mTransientStateViews;
|
||||||
for (int i = 0; i < mTransientStateViews.size(); i++) {
|
if (transViewsByPos != null) {
|
||||||
final View v = mTransientStateViews.valueAt(i);
|
for (int i = 0; i < transViewsByPos.size(); i++) {
|
||||||
|
final View v = transViewsByPos.valueAt(i);
|
||||||
if (!v.hasTransientState()) {
|
if (!v.hasTransientState()) {
|
||||||
mTransientStateViews.removeAt(i);
|
removeDetachedView(v, false);
|
||||||
|
transViewsByPos.removeAt(i);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mTransientStateViewsById != null) {
|
|
||||||
for (int i = 0; i < mTransientStateViewsById.size(); i++) {
|
final LongSparseArray<View> transViewsById = mTransientStateViewsById;
|
||||||
final View v = mTransientStateViewsById.valueAt(i);
|
if (transViewsById != null) {
|
||||||
|
for (int i = 0; i < transViewsById.size(); i++) {
|
||||||
|
final View v = transViewsById.valueAt(i);
|
||||||
if (!v.hasTransientState()) {
|
if (!v.hasTransientState()) {
|
||||||
mTransientStateViewsById.removeAt(i);
|
removeDetachedView(v, false);
|
||||||
|
transViewsById.removeAt(i);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user