Initialize the Choreographer in ReactChoreographer lazily
Summary: Today, ReactInstanceManager calls `ReactChoreographer.initialize()` in its constructor. Since `ReactChoreographer` also needs to run on the UI thread, this forces the entire `ReactInstanceManager` to run on the UI thread. By moving `ReactChoreographer` to lazily set up its Choreographer, we can make `ReactInstanceManager` run on any thread Reviewed By: mdvacca Differential Revision: D10097432 fbshipit-source-id: eb8c80aafcba745ea15c86296d11c487329b1df0
This commit is contained in:
parent
c8b6d606a0
commit
5e7c774d64
|
@ -13,6 +13,7 @@ import android.os.Build;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
|
import com.facebook.react.bridge.UiThreadUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper class for abstracting away availability of the JellyBean Choreographer. If Choreographer
|
* Wrapper class for abstracting away availability of the JellyBean Choreographer. If Choreographer
|
||||||
|
@ -23,13 +24,17 @@ public class ChoreographerCompat {
|
||||||
private static final long ONE_FRAME_MILLIS = 17;
|
private static final long ONE_FRAME_MILLIS = 17;
|
||||||
private static final boolean IS_JELLYBEAN_OR_HIGHER =
|
private static final boolean IS_JELLYBEAN_OR_HIGHER =
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
|
||||||
private static final ChoreographerCompat INSTANCE = new ChoreographerCompat();
|
private static ChoreographerCompat sInstance;
|
||||||
|
|
||||||
private Handler mHandler;
|
private Handler mHandler;
|
||||||
private Choreographer mChoreographer;
|
private Choreographer mChoreographer;
|
||||||
|
|
||||||
public static ChoreographerCompat getInstance() {
|
public static ChoreographerCompat getInstance() {
|
||||||
return INSTANCE;
|
UiThreadUtil.assertOnUiThread();
|
||||||
|
if (sInstance == null){
|
||||||
|
sInstance = new ChoreographerCompat();
|
||||||
|
}
|
||||||
|
return sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChoreographerCompat() {
|
private ChoreographerCompat() {
|
||||||
|
|
|
@ -7,11 +7,12 @@
|
||||||
|
|
||||||
package com.facebook.react.modules.core;
|
package com.facebook.react.modules.core;
|
||||||
|
|
||||||
|
import com.facebook.react.bridge.UiThreadUtil;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.facebook.common.logging.FLog;
|
import com.facebook.common.logging.FLog;
|
||||||
import com.facebook.infer.annotation.Assertions;
|
import com.facebook.infer.annotation.Assertions;
|
||||||
import com.facebook.react.bridge.UiThreadUtil;
|
|
||||||
import com.facebook.react.common.ReactConstants;
|
import com.facebook.react.common.ReactConstants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,7 +66,6 @@ public class ReactChoreographer {
|
||||||
|
|
||||||
public static void initialize() {
|
public static void initialize() {
|
||||||
if (sInstance == null) {
|
if (sInstance == null) {
|
||||||
UiThreadUtil.assertOnUiThread();
|
|
||||||
sInstance = new ReactChoreographer();
|
sInstance = new ReactChoreographer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,8 @@ public class ReactChoreographer {
|
||||||
return sInstance;
|
return sInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ChoreographerCompat mChoreographer;
|
// This needs to be volatile due to double checked locking issue - https://fburl.com/z409owpf
|
||||||
|
private @Nullable volatile ChoreographerCompat mChoreographer;
|
||||||
private final ReactChoreographerDispatcher mReactChoreographerDispatcher;
|
private final ReactChoreographerDispatcher mReactChoreographerDispatcher;
|
||||||
private final ArrayDeque<ChoreographerCompat.FrameCallback>[] mCallbackQueues;
|
private final ArrayDeque<ChoreographerCompat.FrameCallback>[] mCallbackQueues;
|
||||||
|
|
||||||
|
@ -83,12 +84,12 @@ public class ReactChoreographer {
|
||||||
private boolean mHasPostedCallback = false;
|
private boolean mHasPostedCallback = false;
|
||||||
|
|
||||||
private ReactChoreographer() {
|
private ReactChoreographer() {
|
||||||
mChoreographer = ChoreographerCompat.getInstance();
|
|
||||||
mReactChoreographerDispatcher = new ReactChoreographerDispatcher();
|
mReactChoreographerDispatcher = new ReactChoreographerDispatcher();
|
||||||
mCallbackQueues = new ArrayDeque[CallbackType.values().length];
|
mCallbackQueues = new ArrayDeque[CallbackType.values().length];
|
||||||
for (int i = 0; i < mCallbackQueues.length; i++) {
|
for (int i = 0; i < mCallbackQueues.length; i++) {
|
||||||
mCallbackQueues[i] = new ArrayDeque<>();
|
mCallbackQueues[i] = new ArrayDeque<>();
|
||||||
}
|
}
|
||||||
|
initializeChoreographer(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void postFrameCallback(
|
public synchronized void postFrameCallback(
|
||||||
|
@ -98,11 +99,40 @@ public class ReactChoreographer {
|
||||||
mTotalCallbacks++;
|
mTotalCallbacks++;
|
||||||
Assertions.assertCondition(mTotalCallbacks > 0);
|
Assertions.assertCondition(mTotalCallbacks > 0);
|
||||||
if (!mHasPostedCallback) {
|
if (!mHasPostedCallback) {
|
||||||
mChoreographer.postFrameCallback(mReactChoreographerDispatcher);
|
if (mChoreographer == null) {
|
||||||
mHasPostedCallback = true;
|
initializeChoreographer(new Runnable(){
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
postFrameCallbackOnChoreographer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
postFrameCallbackOnChoreographer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void postFrameCallbackOnChoreographer() {
|
||||||
|
mChoreographer.postFrameCallback(mReactChoreographerDispatcher);
|
||||||
|
mHasPostedCallback = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeChoreographer(@Nullable final Runnable runnable) {
|
||||||
|
UiThreadUtil.runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
synchronized (ReactChoreographer.class) {
|
||||||
|
if (mChoreographer == null) {
|
||||||
|
mChoreographer = ChoreographerCompat.getInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (runnable != null) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void removeFrameCallback(
|
public synchronized void removeFrameCallback(
|
||||||
CallbackType type,
|
CallbackType type,
|
||||||
ChoreographerCompat.FrameCallback frameCallback) {
|
ChoreographerCompat.FrameCallback frameCallback) {
|
||||||
|
@ -117,7 +147,9 @@ public class ReactChoreographer {
|
||||||
private void maybeRemoveFrameCallback() {
|
private void maybeRemoveFrameCallback() {
|
||||||
Assertions.assertCondition(mTotalCallbacks >= 0);
|
Assertions.assertCondition(mTotalCallbacks >= 0);
|
||||||
if (mTotalCallbacks == 0 && mHasPostedCallback) {
|
if (mTotalCallbacks == 0 && mHasPostedCallback) {
|
||||||
mChoreographer.removeFrameCallback(mReactChoreographerDispatcher);
|
if (mChoreographer != null) {
|
||||||
|
mChoreographer.removeFrameCallback(mReactChoreographerDispatcher);
|
||||||
|
}
|
||||||
mHasPostedCallback = false;
|
mHasPostedCallback = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue