mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
NativeAnimatedModule: animations should still run if there isn't a Fabric commit for multiple frames
Summary: See videos. In some cases when an `Animated.timing` animation was triggered, there are not necessarily any corresponding Fabric commits. This causes the animations to be queued up but never execute... until there's some Fabric commit at a distant point in the future. We can't immediately flush all animation operations (see inline comments) but we also shouldn't wait forever. Thus, we wait 2 frames and then flush. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D22490650 fbshipit-source-id: 1669bfed00f2a92b50f9558fc7ccaf71dc636980
This commit is contained in:
committed by
Facebook GitHub Bot
parent
7bf56e1902
commit
46d6e7f575
@@ -103,6 +103,7 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
|
||||
private @Nullable NativeAnimatedNodesManager mNodesManager;
|
||||
|
||||
private volatile boolean mFabricBatchCompleted = false;
|
||||
private int mFabricFramesSkipped = 0;
|
||||
private boolean mInitializedForFabric = false;
|
||||
private boolean mInitializedForNonFabric = false;
|
||||
private @UIManagerType int mUIManagerType = UIManagerType.DEFAULT;
|
||||
@@ -174,17 +175,29 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFabricBatchCompleted) {
|
||||
// This will execute all operations and preOperations queued
|
||||
// since the last time this was run, and will race with anything
|
||||
// being queued from the JS thread. That is, if the JS thread
|
||||
// is still queuing operations, we might execute some of them
|
||||
// at the very end until we exhaust the queue faster than the
|
||||
// JS thread can queue up new items.
|
||||
executeAllOperations(mPreOperations);
|
||||
executeAllOperations(mOperations);
|
||||
mFabricBatchCompleted = false;
|
||||
// The problem we're trying to solve here: we could be in the middle of queueing
|
||||
// a batch of related animation operations when Fabric flushes a batch of MountItems.
|
||||
// It's visually bad if we execute half of the animation ops and then wait another frame
|
||||
// (or more) to execute the rest.
|
||||
// Therefore, we wait until either `didScheduleMountItems` has been called, or a certain
|
||||
// number of frames have been skipped.
|
||||
// We wait a max of 2 frames or about 32ms before flushing.
|
||||
// The reason to execute in some cases without a Fabric commit is that there might be
|
||||
// animations that are triggered without any Fabric commits.
|
||||
if (!mFabricBatchCompleted && mFabricFramesSkipped < 3) {
|
||||
mFabricFramesSkipped++;
|
||||
}
|
||||
|
||||
// This will execute all operations and preOperations queued
|
||||
// since the last time this was run, and will race with anything
|
||||
// being queued from the JS thread. That is, if the JS thread
|
||||
// is still queuing operations, we might execute some of them
|
||||
// at the very end until we exhaust the queue faster than the
|
||||
// JS thread can queue up new items.
|
||||
executeAllOperations(mPreOperations);
|
||||
executeAllOperations(mOperations);
|
||||
mFabricBatchCompleted = false;
|
||||
mFabricFramesSkipped = 0;
|
||||
}
|
||||
|
||||
private void executeAllOperations(Queue<UIThreadOperation> operationQueue) {
|
||||
|
||||
Reference in New Issue
Block a user