move NativeModule initialization off UI thread

Summary: Initializing natives modules on the UI thread blocks the JS thread if the UI thread is busy.

Reviewed By: yungsters

Differential Revision: D4611211

fbshipit-source-id: cd4fb9cb5e52a478b6692b784cfd9e3bf34c0d34
This commit is contained in:
Aaron Chiu
2017-03-06 21:01:48 -08:00
committed by Facebook Github Bot
parent e32e4d9711
commit b085215237
10 changed files with 116 additions and 82 deletions

View File

@@ -11,6 +11,8 @@ package com.facebook.react.animated;
import javax.annotation.Nullable;
import java.util.ArrayList;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
@@ -27,8 +29,6 @@ import com.facebook.react.modules.core.ReactChoreographer;
import com.facebook.react.uimanager.GuardedFrameCallback;
import com.facebook.react.uimanager.UIManagerModule;
import java.util.ArrayList;
/**
* Module that exposes interface for creating and managing animated nodes on the "native" side.
*
@@ -90,43 +90,50 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
@Override
public void initialize() {
// Safe to acquire choreographer here, as initialize() is invoked from UI thread.
mReactChoreographer = ReactChoreographer.getInstance();
getReactApplicationContext().addLifecycleEventListener(this);
}
ReactApplicationContext reactCtx = getReactApplicationContext();
UIManagerModule uiManager = reactCtx.getNativeModule(UIManagerModule.class);
@Override
public void onHostResume() {
if (mReactChoreographer == null) {
// Safe to acquire choreographer here, as onHostResume() is invoked from UI thread.
mReactChoreographer = ReactChoreographer.getInstance();
final NativeAnimatedNodesManager nodesManager = new NativeAnimatedNodesManager(uiManager);
mAnimatedFrameCallback = new GuardedFrameCallback(reactCtx) {
@Override
protected void doFrameGuarded(final long frameTimeNanos) {
ReactApplicationContext reactCtx = getReactApplicationContext();
UIManagerModule uiManager = reactCtx.getNativeModule(UIManagerModule.class);
ArrayList<UIThreadOperation> operations;
synchronized (mOperationsCopyLock) {
operations = mReadyOperations;
mReadyOperations = null;
}
final NativeAnimatedNodesManager nodesManager = new NativeAnimatedNodesManager(uiManager);
mAnimatedFrameCallback = new GuardedFrameCallback(reactCtx) {
@Override
protected void doFrameGuarded(final long frameTimeNanos) {
if (operations != null) {
for (int i = 0, size = operations.size(); i < size; i++) {
operations.get(i).execute(nodesManager);
ArrayList<UIThreadOperation> operations;
synchronized (mOperationsCopyLock) {
operations = mReadyOperations;
mReadyOperations = null;
}
}
if (nodesManager.hasActiveAnimations()) {
nodesManager.runUpdates(frameTimeNanos);
}
if (operations != null) {
for (int i = 0, size = operations.size(); i < size; i++) {
operations.get(i).execute(nodesManager);
}
}
// TODO: Would be great to avoid adding this callback in case there are no active animations
// and no outstanding tasks on the operations queue. Apparently frame callbacks can only
// be posted from the UI thread and therefore we cannot schedule them directly from
// @ReactMethod methods
Assertions.assertNotNull(mReactChoreographer).postFrameCallback(
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
mAnimatedFrameCallback);
}
};
reactCtx.addLifecycleEventListener(this);
if (nodesManager.hasActiveAnimations()) {
nodesManager.runUpdates(frameTimeNanos);
}
// TODO: Would be great to avoid adding this callback in case there are no active animations
// and no outstanding tasks on the operations queue. Apparently frame callbacks can only
// be posted from the UI thread and therefore we cannot schedule them directly from
// @ReactMethod methods
Assertions.assertNotNull(mReactChoreographer).postFrameCallback(
ReactChoreographer.CallbackType.NATIVE_ANIMATED_MODULE,
mAnimatedFrameCallback);
}
};
}
enqueueFrameCallback();
}
@Override
@@ -150,11 +157,6 @@ public class NativeAnimatedModule extends ReactContextBaseJavaModule implements
}
}
@Override
public void onHostResume() {
enqueueFrameCallback();
}
@Override
public void onHostPause() {
clearFrameCallback();