private void moveStagedEventsToDispatchQueue(){
synchronized (mEventsStagingLock) {
synchronized (mEventsToDispatchLock) {
      for (int i=0; i < mEventStaging.size(); i++) {
        Event event=mEventStaging.get(i);
        if (!event.canCoalesce()) {
          addEventToEventsToDispatch(event);
          continue;
        }
        long eventCookie=getEventCookie(event.getViewTag(),event.getEventName(),event.getCoalescingKey());
        Event eventToAdd=null;
        Event eventToDispose=null;
        Integer lastEventIdx=mEventCookieToLastEventIdx.get(eventCookie);
        if (lastEventIdx == null) {
          eventToAdd=event;
          mEventCookieToLastEventIdx.put(eventCookie,mEventsToDispatchSize);
        }
 else {
          Event lastEvent=mEventsToDispatch[lastEventIdx];
          Event coalescedEvent=event.coalesce(lastEvent);
          if (coalescedEvent != lastEvent) {
            eventToAdd=coalescedEvent;
            mEventCookieToLastEventIdx.put(eventCookie,mEventsToDispatchSize);
            eventToDispose=lastEvent;
            mEventsToDispatch[lastEventIdx]=null;
          }
 else {
            eventToDispose=event;
          }
        }
        if (eventToAdd != null) {
          addEventToEventsToDispatch(eventToAdd);
        }
        if (eventToDispose != null) {
          eventToDispose.dispose();
        }
      }
    }
    mEventStaging.clear();
  }
}

private void moveStagedEventsToDispatchQueue ( ) { synchronized ( mEventsStagingLock ) { synchronized ( mEventsToDispatchLock ) { for ( int i = 0 ; i < mEventStaging . size ( ) ; i ++ ) { Event event = mEventStaging . get ( i ) ; if ( ! event . canCoalesce ( ) ) { addEventToEventsToDispatch ( event ) ; continue ; } long eventCookie = getEventCookie ( event . getViewTag ( ) , event . getEventName ( ) , event . getCoalescingKey ( ) ) ; Event eventToAdd = null ; Event eventToDispose = null ; Integer lastEventIdx = mEventCookieToLastEventIdx . get ( eventCookie ) ; if ( lastEventIdx == null ) { eventToAdd = event ; mEventCookieToLastEventIdx . put ( eventCookie , mEventsToDispatchSize ) ; } else { Event lastEvent = mEventsToDispatch [ lastEventIdx ] ; Event coalescedEvent = event . coalesce ( lastEvent ) ; if ( coalescedEvent != lastEvent ) { eventToAdd = coalescedEvent ; mEventCookieToLastEventIdx . put ( eventCookie , mEventsToDispatchSize ) ; eventToDispose = lastEvent ; mEventsToDispatch [ lastEventIdx ] = null ; } else { eventToDispose = event ; } } if ( eventToAdd != null ) { addEventToEventsToDispatch ( eventToAdd ) ; } if ( eventToDispose != null ) { eventToDispose . dispose ( ) ; } } } mEventStaging . clear ( ) ; } }
we use a staging data structure so that all ui events generated in a single frame are dispatched at once . otherwise , a js runnable enqueued in a previous frame could run while the ui thread is in the process of adding ui events and we might incorrectly send one event this frame and another from this frame during the next .
