1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2013 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezpackage org.chromium.base; 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.util.ArrayList; 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.util.Iterator; 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.util.List; 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport java.util.NoSuchElementException; 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport javax.annotation.concurrent.NotThreadSafe; 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez/** 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * A container for a list of observers. 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * <p/> 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * This container can be modified during iteration without invalidating the iterator. 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * So, it safely handles the case of an observer removing itself or other observers from the list 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * while observers are being notified. 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * <p/> 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * The implementation (and the interface) is heavily influenced by the C++ ObserverList. 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Notable differences: 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - The iterator implements NOTIFY_EXISTING_ONLY. 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * - The FOR_EACH_OBSERVER closure is left to the clients to implement in terms of iterator(). 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * <p/> 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * This class is not threadsafe. Observers MUST be added, removed and will be notified on the same 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * thread this is created. 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @param <E> The type of observers that this list should hold. 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@NotThreadSafe 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezpublic class ObserverList<E> implements Iterable<E> { 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Extended iterator interface that provides rewind functionality. 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public interface RewindableIterator<E> extends Iterator<E> { 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Rewind the iterator back to the beginning. 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * If we need to iterate multiple times, we can avoid iterator object reallocation by using 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * this method. 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void rewind(); 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public final List<E> mObservers = new ArrayList<E>(); 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private int mIterationDepth = 0; 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private int mCount = 0; 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private boolean mNeedsCompact = false; 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public ObserverList() {} 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Add an observer to the list. 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * <p/> 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * An observer should not be added to the same list more than once. If an iteration is already 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * in progress, this observer will be not be visible during that iteration. 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return true if the observer list changed as a result of the call. 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public boolean addObserver(E obs) { 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Avoid adding null elements to the list as they may be removed on a compaction. 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (obs == null || mObservers.contains(obs)) { 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Structurally modifying the underlying list here. This means we 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // cannot use the underlying list's iterator to iterate over the list. 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez boolean result = mObservers.add(obs); 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assert result; 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ++mCount; 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Remove an observer from the list if it is in the list. 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * @return true if an element was removed as a result of this call. 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public boolean removeObserver(E obs) { 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (obs == null) { 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int index = mObservers.indexOf(obs); 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (index == -1) { 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mIterationDepth == 0) { 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // No one is iterating over the list. 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mObservers.remove(index); 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mNeedsCompact = true; 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mObservers.set(index, null); 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez --mCount; 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assert mCount >= 0; 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public boolean hasObserver(E obs) { 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return mObservers.contains(obs); 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void clear() { 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mCount = 0; 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mIterationDepth == 0) { 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mObservers.clear(); 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int size = mObservers.size(); 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mNeedsCompact |= size != 0; 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (int i = 0; i < size; i++) { 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mObservers.set(i, null); 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public Iterator<E> iterator() { 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return new ObserverListIterator(); 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * It's the same as {@link ObserverList#iterator()} but the return type is 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * {@link RewindableIterator}. Use this iterator type if you need to use 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * {@link RewindableIterator#rewind()}. 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public RewindableIterator<E> rewindableIterator() { 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return new ObserverListIterator(); 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Returns the number of observers currently registered in the ObserverList. 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * This is equivalent to the number of non-empty spaces in |mObservers|. 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public int size() { 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return mCount; 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Returns true if the ObserverList contains no observers. 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public boolean isEmpty() { 149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return mCount == 0; 150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Compact the underlying list be removing null elements. 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * <p/> 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Should only be called when mIterationDepth is zero. 156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void compact() { 158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assert mIterationDepth == 0; 159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (int i = mObservers.size() - 1; i >= 0; i--) { 160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mObservers.get(i) == null) { 161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mObservers.remove(i); 162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void incrementIterationDepth() { 167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mIterationDepth++; 168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void decrementIterationDepthAndCompactIfNeeded() { 171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mIterationDepth--; 172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez assert mIterationDepth >= 0; 173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mIterationDepth > 0) return; 174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!mNeedsCompact) return; 175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mNeedsCompact = false; 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez compact(); 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez /** 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * Returns the size of the underlying storage of the ObserverList. 181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez * It will take into account the empty spaces inside |mObservers|. 182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez */ 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private int capacity() { 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return mObservers.size(); 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private E getObserverAt(int index) { 188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return mObservers.get(index); 189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private class ObserverListIterator implements RewindableIterator<E> { 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private int mListEndMarker; 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private int mIndex = 0; 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private boolean mIsExhausted = false; 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private ObserverListIterator() { 197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ObserverList.this.incrementIterationDepth(); 198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mListEndMarker = ObserverList.this.capacity(); 199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void rewind() { 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez compactListIfNeeded(); 204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ObserverList.this.incrementIterationDepth(); 205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mListEndMarker = ObserverList.this.capacity(); 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mIsExhausted = false; 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mIndex = 0; 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public boolean hasNext() { 212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez int lookupIndex = mIndex; 213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez while (lookupIndex < mListEndMarker 214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez && ObserverList.this.getObserverAt(lookupIndex) == null) { 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez lookupIndex++; 216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (lookupIndex < mListEndMarker) return true; 218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We have reached the end of the list, allow for compaction. 220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez compactListIfNeeded(); 221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public E next() { 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Advance if the current element is null. 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez while (mIndex < mListEndMarker && ObserverList.this.getObserverAt(mIndex) == null) { 228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mIndex++; 229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mIndex < mListEndMarker) return ObserverList.this.getObserverAt(mIndex++); 231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We have reached the end of the list, allow for compaction. 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez compactListIfNeeded(); 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new NoSuchElementException(); 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @Override 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public void remove() { 239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez throw new UnsupportedOperationException(); 240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private void compactListIfNeeded() { 243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!mIsExhausted) { 244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mIsExhausted = true; 245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ObserverList.this.decrementIterationDepthAndCompactIfNeeded(); 246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 250