Loading core/java/android/view/ViewTreeObserver.java +45 −161 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.graphics.Rect; import android.graphics.Region; import java.util.ArrayList; import java.util.concurrent.CopyOnWriteArrayList; /** * A view tree observer is used to register listeners that can be notified of global Loading @@ -31,12 +32,12 @@ import java.util.ArrayList; * for more information. */ public final class ViewTreeObserver { private CopyOnWriteArray<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; private CopyOnWriteArray<OnGlobalLayoutListener> mOnGlobalLayoutListeners; private CopyOnWriteArray<OnTouchModeChangeListener> mOnTouchModeChangeListeners; private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners; private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners; private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; private CopyOnWriteArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners; private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners; private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners; private ArrayList<OnPreDrawListener> mOnPreDrawListeners; private ArrayList<OnDrawListener> mOnDrawListeners; private boolean mAlive = true; Loading Loading @@ -327,7 +328,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnGlobalFocusListeners == null) { mOnGlobalFocusListeners = new CopyOnWriteArray<OnGlobalFocusChangeListener>(); mOnGlobalFocusListeners = new CopyOnWriteArrayList<OnGlobalFocusChangeListener>(); } mOnGlobalFocusListeners.add(listener); Loading Loading @@ -362,7 +363,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnGlobalLayoutListeners == null) { mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>(); mOnGlobalLayoutListeners = new CopyOnWriteArrayList<OnGlobalLayoutListener>(); } mOnGlobalLayoutListeners.add(listener); Loading Loading @@ -412,7 +413,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnPreDrawListeners == null) { mOnPreDrawListeners = new CopyOnWriteArray<OnPreDrawListener>(); mOnPreDrawListeners = new ArrayList<OnPreDrawListener>(); } mOnPreDrawListeners.add(listener); Loading Loading @@ -484,7 +485,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnScrollChangedListeners == null) { mOnScrollChangedListeners = new CopyOnWriteArray<OnScrollChangedListener>(); mOnScrollChangedListeners = new CopyOnWriteArrayList<OnScrollChangedListener>(); } mOnScrollChangedListeners.add(listener); Loading Loading @@ -518,7 +519,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnTouchModeChangeListeners == null) { mOnTouchModeChangeListeners = new CopyOnWriteArray<OnTouchModeChangeListener>(); mOnTouchModeChangeListeners = new CopyOnWriteArrayList<OnTouchModeChangeListener>(); } mOnTouchModeChangeListeners.add(listener); Loading Loading @@ -557,7 +558,7 @@ public final class ViewTreeObserver { if (mOnComputeInternalInsetsListeners == null) { mOnComputeInternalInsetsListeners = new CopyOnWriteArray<OnComputeInternalInsetsListener>(); new CopyOnWriteArrayList<OnComputeInternalInsetsListener>(); } mOnComputeInternalInsetsListeners.add(listener); Loading Loading @@ -621,16 +622,10 @@ public final class ViewTreeObserver { // perform the dispatching. The iterator is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we iterate it. final CopyOnWriteArray<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners; final CopyOnWriteArrayList<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnGlobalFocusChangeListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onGlobalFocusChanged(oldFocus, newFocus); } } finally { listeners.end(); for (OnGlobalFocusChangeListener listener : listeners) { listener.onGlobalFocusChanged(oldFocus, newFocus); } } } Loading @@ -645,16 +640,10 @@ public final class ViewTreeObserver { // perform the dispatching. The iterator is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we iterate it. final CopyOnWriteArray<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners; final CopyOnWriteArrayList<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnGlobalLayoutListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onGlobalLayout(); } } finally { listeners.end(); for (OnGlobalLayoutListener listener : listeners) { listener.onGlobalLayout(); } } } Loading @@ -669,17 +658,17 @@ public final class ViewTreeObserver { */ @SuppressWarnings("unchecked") public final boolean dispatchOnPreDraw() { // NOTE: we *must* clone the listener list to perform the dispatching. // The clone is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we process it. boolean cancelDraw = false; final CopyOnWriteArray<OnPreDrawListener> listeners = mOnPreDrawListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnPreDrawListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { cancelDraw |= !(access.get(i).onPreDraw()); } } finally { listeners.end(); if (mOnPreDrawListeners != null && mOnPreDrawListeners.size() > 0) { final ArrayList<OnPreDrawListener> listeners = (ArrayList<OnPreDrawListener>) mOnPreDrawListeners.clone(); int numListeners = listeners.size(); for (int i = 0; i < numListeners; ++i) { cancelDraw |= !(listeners.get(i).onPreDraw()); } } return cancelDraw; Loading @@ -704,17 +693,11 @@ public final class ViewTreeObserver { * @param inTouchMode True if the touch mode is now enabled, false otherwise. */ final void dispatchOnTouchModeChanged(boolean inTouchMode) { final CopyOnWriteArray<OnTouchModeChangeListener> listeners = final CopyOnWriteArrayList<OnTouchModeChangeListener> listeners = mOnTouchModeChangeListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnTouchModeChangeListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onTouchModeChanged(inTouchMode); } } finally { listeners.end(); for (OnTouchModeChangeListener listener : listeners) { listener.onTouchModeChanged(inTouchMode); } } } Loading @@ -727,16 +710,10 @@ public final class ViewTreeObserver { // perform the dispatching. The iterator is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we iterate it. final CopyOnWriteArray<OnScrollChangedListener> listeners = mOnScrollChangedListeners; final CopyOnWriteArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnScrollChangedListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onScrollChanged(); } } finally { listeners.end(); for (OnScrollChangedListener listener : listeners) { listener.onScrollChanged(); } } } Loading @@ -745,7 +722,7 @@ public final class ViewTreeObserver { * Returns whether there are listeners for computing internal insets. */ final boolean hasComputeInternalInsetsListeners() { final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners = final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; return (listeners != null && listeners.size() > 0); } Loading @@ -758,105 +735,12 @@ public final class ViewTreeObserver { // perform the dispatching. The iterator is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we iterate it. final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners = final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnComputeInternalInsetsListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onComputeInternalInsets(inoutInfo); } } finally { listeners.end(); } } } /** * Copy on write array. This array is not thread safe, and only one loop can * iterate over this array at any given time. This class avoids allocations * until a concurrent modification happens. * * Usage: * * CopyOnWriteArray.Access<MyData> access = array.start(); * try { * for (int i = 0; i < access.size(); i++) { * MyData d = access.get(i); * } * } finally { * access.end(); * } */ static class CopyOnWriteArray<T> { private ArrayList<T> mData = new ArrayList<T>(); private ArrayList<T> mDataCopy; private final Access<T> mAccess = new Access<T>(); private boolean mStart; static class Access<T> { private ArrayList<T> mData; private int mSize; T get(int index) { return mData.get(index); for (OnComputeInternalInsetsListener listener : listeners) { listener.onComputeInternalInsets(inoutInfo); } int size() { return mSize; } } CopyOnWriteArray() { } private ArrayList<T> getArray() { if (mStart) { if (mDataCopy == null) mDataCopy = new ArrayList<T>(mData); return mDataCopy; } return mData; } Access<T> start() { if (mStart) throw new IllegalStateException("Iteration already started"); mStart = true; mDataCopy = null; mAccess.mData = mData; mAccess.mSize = mData.size(); return mAccess; } void end() { if (!mStart) throw new IllegalStateException("Iteration not started"); mStart = false; if (mDataCopy != null) { mData = mDataCopy; } mDataCopy = null; } int size() { return getArray().size(); } void add(T item) { getArray().add(item); } void addAll(CopyOnWriteArray<T> array) { getArray().addAll(array.mData); } void remove(T item) { getArray().remove(item); } void clear() { getArray().clear(); } } } Loading
core/java/android/view/ViewTreeObserver.java +45 −161 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.graphics.Rect; import android.graphics.Region; import java.util.ArrayList; import java.util.concurrent.CopyOnWriteArrayList; /** * A view tree observer is used to register listeners that can be notified of global Loading @@ -31,12 +32,12 @@ import java.util.ArrayList; * for more information. */ public final class ViewTreeObserver { private CopyOnWriteArray<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; private CopyOnWriteArray<OnGlobalLayoutListener> mOnGlobalLayoutListeners; private CopyOnWriteArray<OnTouchModeChangeListener> mOnTouchModeChangeListeners; private CopyOnWriteArray<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; private CopyOnWriteArray<OnScrollChangedListener> mOnScrollChangedListeners; private CopyOnWriteArray<OnPreDrawListener> mOnPreDrawListeners; private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners; private CopyOnWriteArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners; private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners; private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners; private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners; private ArrayList<OnPreDrawListener> mOnPreDrawListeners; private ArrayList<OnDrawListener> mOnDrawListeners; private boolean mAlive = true; Loading Loading @@ -327,7 +328,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnGlobalFocusListeners == null) { mOnGlobalFocusListeners = new CopyOnWriteArray<OnGlobalFocusChangeListener>(); mOnGlobalFocusListeners = new CopyOnWriteArrayList<OnGlobalFocusChangeListener>(); } mOnGlobalFocusListeners.add(listener); Loading Loading @@ -362,7 +363,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnGlobalLayoutListeners == null) { mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>(); mOnGlobalLayoutListeners = new CopyOnWriteArrayList<OnGlobalLayoutListener>(); } mOnGlobalLayoutListeners.add(listener); Loading Loading @@ -412,7 +413,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnPreDrawListeners == null) { mOnPreDrawListeners = new CopyOnWriteArray<OnPreDrawListener>(); mOnPreDrawListeners = new ArrayList<OnPreDrawListener>(); } mOnPreDrawListeners.add(listener); Loading Loading @@ -484,7 +485,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnScrollChangedListeners == null) { mOnScrollChangedListeners = new CopyOnWriteArray<OnScrollChangedListener>(); mOnScrollChangedListeners = new CopyOnWriteArrayList<OnScrollChangedListener>(); } mOnScrollChangedListeners.add(listener); Loading Loading @@ -518,7 +519,7 @@ public final class ViewTreeObserver { checkIsAlive(); if (mOnTouchModeChangeListeners == null) { mOnTouchModeChangeListeners = new CopyOnWriteArray<OnTouchModeChangeListener>(); mOnTouchModeChangeListeners = new CopyOnWriteArrayList<OnTouchModeChangeListener>(); } mOnTouchModeChangeListeners.add(listener); Loading Loading @@ -557,7 +558,7 @@ public final class ViewTreeObserver { if (mOnComputeInternalInsetsListeners == null) { mOnComputeInternalInsetsListeners = new CopyOnWriteArray<OnComputeInternalInsetsListener>(); new CopyOnWriteArrayList<OnComputeInternalInsetsListener>(); } mOnComputeInternalInsetsListeners.add(listener); Loading Loading @@ -621,16 +622,10 @@ public final class ViewTreeObserver { // perform the dispatching. The iterator is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we iterate it. final CopyOnWriteArray<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners; final CopyOnWriteArrayList<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnGlobalFocusChangeListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onGlobalFocusChanged(oldFocus, newFocus); } } finally { listeners.end(); for (OnGlobalFocusChangeListener listener : listeners) { listener.onGlobalFocusChanged(oldFocus, newFocus); } } } Loading @@ -645,16 +640,10 @@ public final class ViewTreeObserver { // perform the dispatching. The iterator is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we iterate it. final CopyOnWriteArray<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners; final CopyOnWriteArrayList<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnGlobalLayoutListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onGlobalLayout(); } } finally { listeners.end(); for (OnGlobalLayoutListener listener : listeners) { listener.onGlobalLayout(); } } } Loading @@ -669,17 +658,17 @@ public final class ViewTreeObserver { */ @SuppressWarnings("unchecked") public final boolean dispatchOnPreDraw() { // NOTE: we *must* clone the listener list to perform the dispatching. // The clone is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we process it. boolean cancelDraw = false; final CopyOnWriteArray<OnPreDrawListener> listeners = mOnPreDrawListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnPreDrawListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { cancelDraw |= !(access.get(i).onPreDraw()); } } finally { listeners.end(); if (mOnPreDrawListeners != null && mOnPreDrawListeners.size() > 0) { final ArrayList<OnPreDrawListener> listeners = (ArrayList<OnPreDrawListener>) mOnPreDrawListeners.clone(); int numListeners = listeners.size(); for (int i = 0; i < numListeners; ++i) { cancelDraw |= !(listeners.get(i).onPreDraw()); } } return cancelDraw; Loading @@ -704,17 +693,11 @@ public final class ViewTreeObserver { * @param inTouchMode True if the touch mode is now enabled, false otherwise. */ final void dispatchOnTouchModeChanged(boolean inTouchMode) { final CopyOnWriteArray<OnTouchModeChangeListener> listeners = final CopyOnWriteArrayList<OnTouchModeChangeListener> listeners = mOnTouchModeChangeListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnTouchModeChangeListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onTouchModeChanged(inTouchMode); } } finally { listeners.end(); for (OnTouchModeChangeListener listener : listeners) { listener.onTouchModeChanged(inTouchMode); } } } Loading @@ -727,16 +710,10 @@ public final class ViewTreeObserver { // perform the dispatching. The iterator is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we iterate it. final CopyOnWriteArray<OnScrollChangedListener> listeners = mOnScrollChangedListeners; final CopyOnWriteArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnScrollChangedListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onScrollChanged(); } } finally { listeners.end(); for (OnScrollChangedListener listener : listeners) { listener.onScrollChanged(); } } } Loading @@ -745,7 +722,7 @@ public final class ViewTreeObserver { * Returns whether there are listeners for computing internal insets. */ final boolean hasComputeInternalInsetsListeners() { final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners = final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; return (listeners != null && listeners.size() > 0); } Loading @@ -758,105 +735,12 @@ public final class ViewTreeObserver { // perform the dispatching. The iterator is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we iterate it. final CopyOnWriteArray<OnComputeInternalInsetsListener> listeners = final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners; if (listeners != null && listeners.size() > 0) { CopyOnWriteArray.Access<OnComputeInternalInsetsListener> access = listeners.start(); try { int count = access.size(); for (int i = 0; i < count; i++) { access.get(i).onComputeInternalInsets(inoutInfo); } } finally { listeners.end(); } } } /** * Copy on write array. This array is not thread safe, and only one loop can * iterate over this array at any given time. This class avoids allocations * until a concurrent modification happens. * * Usage: * * CopyOnWriteArray.Access<MyData> access = array.start(); * try { * for (int i = 0; i < access.size(); i++) { * MyData d = access.get(i); * } * } finally { * access.end(); * } */ static class CopyOnWriteArray<T> { private ArrayList<T> mData = new ArrayList<T>(); private ArrayList<T> mDataCopy; private final Access<T> mAccess = new Access<T>(); private boolean mStart; static class Access<T> { private ArrayList<T> mData; private int mSize; T get(int index) { return mData.get(index); for (OnComputeInternalInsetsListener listener : listeners) { listener.onComputeInternalInsets(inoutInfo); } int size() { return mSize; } } CopyOnWriteArray() { } private ArrayList<T> getArray() { if (mStart) { if (mDataCopy == null) mDataCopy = new ArrayList<T>(mData); return mDataCopy; } return mData; } Access<T> start() { if (mStart) throw new IllegalStateException("Iteration already started"); mStart = true; mDataCopy = null; mAccess.mData = mData; mAccess.mSize = mData.size(); return mAccess; } void end() { if (!mStart) throw new IllegalStateException("Iteration not started"); mStart = false; if (mDataCopy != null) { mData = mDataCopy; } mDataCopy = null; } int size() { return getArray().size(); } void add(T item) { getArray().add(item); } void addAll(CopyOnWriteArray<T> array) { getArray().addAll(array.mData); } void remove(T item) { getArray().remove(item); } void clear() { getArray().clear(); } } }