         }
         pendingResponders.length = 0;
         failedItems.length = 0;
+    }
+    
+    /**
+     *  The previous known length of the list before handling a CollectionEvent.
+     *  oldLength is updated by the list setter and isValidCollectionEvent().
+     */
+    private var oldLength:int = -1;
+    
+    /**
+     *  This method checks the validity of incoming CollectionEvents. 
+     *  In some cases, a CollectionEvent from the underlying list may have already
+     *  been received once, or have been erroneously dispatched (See SDK-30594).
+     *  Thus, we check the incoming event's location against the last known length'
+     *  of the list (oldLength).
+     * 
+     *  <p>Returns false if the index is less than 0 or greater than the previous
+     *  length of the list.
+     *  This only applies to ADD, REMOVE, REPLACE, and MOVE CollectionEvents.
+     *  It also updates oldLength to be the current length of the list, so it
+     *  should not be called twice.</p>
+     */
+    private function isValidCollectionEvent(ce:CollectionEvent):Boolean
+    {
+        if (oldLength < 0)
+            return true;
+        
+        const location:int = ce.location;
+        
+        switch (ce.kind)
+        {
+            case CollectionEventKind.ADD:
+            {
+                if (location < 0 || location > oldLength)
+                    return false;
+                break;
+            }
+                
+            case CollectionEventKind.REMOVE:
+            case CollectionEventKind.REPLACE:
+            case CollectionEventKind.MOVE:
+            {
+                if (location < 0 || location >= oldLength)
+                    return false;
+                break;
+            }
+        }
+        
+        oldLength = length;
+        return true;
     }
 
     /**

     *  
     *  All "collectionChange" events are redispatched to the AsyncListView listeners.
     */
    private function handleCollectionChangeEvent(e:Event):void
    {
        const ce:CollectionEvent = CollectionEvent(e);
        switch (ce.kind)
        {
            case CollectionEventKind.REPLACE:

                deleteAllPendingResponders();
                break;
        }

        dispatchEvent(ce);  // redispatch to CollectionEvent listeners on this
    }
    
    /**
     *  @private
     *  Delete the ListItemResponder at the specified index, if any.
