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.Looper;
|
||||
import android.view.Choreographer;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
|
||||
/**
|
||||
* 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 boolean IS_JELLYBEAN_OR_HIGHER =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
|
||||
private static final ChoreographerCompat INSTANCE = new ChoreographerCompat();
|
||||
private static ChoreographerCompat sInstance;
|
||||
|
||||
private Handler mHandler;
|
||||
private Choreographer mChoreographer;
|
||||
|
||||
public static ChoreographerCompat getInstance() {
|
||||
return INSTANCE;
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
if (sInstance == null){
|
||||
sInstance = new ChoreographerCompat();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private ChoreographerCompat() {
|
||||
|
|
|
@ -7,11 +7,12 @@
|
|||
|
||||
package com.facebook.react.modules.core;
|
||||
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import java.util.ArrayDeque;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.UiThreadUtil;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
|
||||
/**
|
||||
|
@ -65,7 +66,6 @@ public class ReactChoreographer {
|
|||
|
||||
public static void initialize() {
|
||||
if (sInstance == null) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
sInstance = new ReactChoreographer();
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,8 @@ public class ReactChoreographer {
|
|||
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 ArrayDeque<ChoreographerCompat.FrameCallback>[] mCallbackQueues;
|
||||
|
||||
|
@ -83,12 +84,12 @@ public class ReactChoreographer {
|
|||
private boolean mHasPostedCallback = false;
|
||||
|
||||
private ReactChoreographer() {
|
||||
mChoreographer = ChoreographerCompat.getInstance();
|
||||
mReactChoreographerDispatcher = new ReactChoreographerDispatcher();
|
||||
mCallbackQueues = new ArrayDeque[CallbackType.values().length];
|
||||
for (int i = 0; i < mCallbackQueues.length; i++) {
|
||||
mCallbackQueues[i] = new ArrayDeque<>();
|
||||
}
|
||||
initializeChoreographer(null);
|
||||
}
|
||||
|
||||
public synchronized void postFrameCallback(
|
||||
|
@ -98,11 +99,40 @@ public class ReactChoreographer {
|
|||
mTotalCallbacks++;
|
||||
Assertions.assertCondition(mTotalCallbacks > 0);
|
||||
if (!mHasPostedCallback) {
|
||||
mChoreographer.postFrameCallback(mReactChoreographerDispatcher);
|
||||
mHasPostedCallback = true;
|
||||
if (mChoreographer == null) {
|
||||
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(
|
||||
CallbackType type,
|
||||
ChoreographerCompat.FrameCallback frameCallback) {
|
||||
|
@ -117,7 +147,9 @@ public class ReactChoreographer {
|
|||
private void maybeRemoveFrameCallback() {
|
||||
Assertions.assertCondition(mTotalCallbacks >= 0);
|
||||
if (mTotalCallbacks == 0 && mHasPostedCallback) {
|
||||
mChoreographer.removeFrameCallback(mReactChoreographerDispatcher);
|
||||
if (mChoreographer != null) {
|
||||
mChoreographer.removeFrameCallback(mReactChoreographerDispatcher);
|
||||
}
|
||||
mHasPostedCallback = false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue