Skip to content
Permalink
Browse files

Fix bug where UIOperations aren't executed after hosting Activity is …

…paused.

Summary:
When we hit the back button and unmount the ReactRootView, we tell JS to unmount the application root node, which causes JS to asynchronously come back and tell the UIManager to drop the corresponding root view.

This issue was that by the time JS gets back to us, we likely will have already paused the UIManager frame callback which means the view unmounting never actually happens: it just gets stuck in the queue.

The solution is to immediately execute batches when they are enqueued when the frame callback isn't running.

Reviewed By: lexs

Differential Revision: D3398958

fbshipit-source-id: 0de81061a97a119be4cb0b12d6f01c1cec8e8171
  • Loading branch information...
astreet authored and Facebook Github Bot 4 committed Jun 9, 2016
1 parent 5ef3b47 commit eef03fd5524887da19eb413658c021f9c806af1d
Showing with 27 additions and 8 deletions.
  1. +27 −8 ReactAndroid/src/main/java/com/facebook/react/uimanager/UIViewOperationQueue.java
@@ -521,8 +521,8 @@ public void execute() {
private ArrayList<UIOperation> mOperations = new ArrayList<>();
@GuardedBy("mNonBatchedOperationsLock")
private ArrayDeque<UIOperation> mNonBatchedOperations = new ArrayDeque<>();

private @Nullable NotThreadSafeViewHierarchyUpdateDebugListener mViewHierarchyUpdateDebugListener;
private boolean mIsDispatchUIFrameCallbackEnqueued = false;

public UIViewOperationQueue(
ReactApplicationContext reactContext,
@@ -779,17 +779,41 @@ public void run() {
}
});
}

// In the case where the frame callback isn't enqueued, the UI isn't being displayed or is being
// destroyed. In this case it's no longer important to align to frames, but it is imporant to make
// sure any late-arriving UI commands are executed.
if (!mIsDispatchUIFrameCallbackEnqueued) {
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
flushPendingBatches();
}
});
}
}

/* package */ void resumeFrameCallback() {
mIsDispatchUIFrameCallbackEnqueued = true;
ReactChoreographer.getInstance()
.postFrameCallback(ReactChoreographer.CallbackType.DISPATCH_UI, mDispatchUIFrameCallback);
}

/* package */ void pauseFrameCallback() {

mIsDispatchUIFrameCallbackEnqueued = false;
ReactChoreographer.getInstance()
.removeFrameCallback(ReactChoreographer.CallbackType.DISPATCH_UI, mDispatchUIFrameCallback);
flushPendingBatches();
}

private void flushPendingBatches() {
synchronized (mDispatchRunnablesLock) {
for (int i = 0; i < mDispatchUIRunnables.size(); i++) {
mDispatchUIRunnables.get(i).run();
}
mDispatchUIRunnables.clear();
}
}

/**
@@ -825,12 +849,7 @@ public void doFrameGuarded(long frameTimeNanos) {
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
}

synchronized (mDispatchRunnablesLock) {
for (int i = 0; i < mDispatchUIRunnables.size(); i++) {
mDispatchUIRunnables.get(i).run();
}
mDispatchUIRunnables.clear();
}
flushPendingBatches();

ReactChoreographer.getInstance().postFrameCallback(
ReactChoreographer.CallbackType.DISPATCH_UI, this);

0 comments on commit eef03fd

Please sign in to comment.
You can’t perform that action at this time.