forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Convert modules/core/ReactChoreographer to Kotlin (facebook#45811)
Summary: Pull Request resolved: facebook#45811 # Changelog: [Internal] - Converts both ReactChoreographer.java and ChoreographerCompat.java to Kotlin. Reviewed By: mdvacca Differential Revision: D60445731
- Loading branch information
1 parent
c30ee46
commit 1695180
Showing
7 changed files
with
197 additions
and
213 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 0 additions & 18 deletions
18
...ative/ReactAndroid/src/main/java/com/facebook/react/modules/core/ChoreographerCompat.java
This file was deleted.
Oops, something went wrong.
16 changes: 16 additions & 0 deletions
16
...-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/ChoreographerCompat.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
package com.facebook.react.modules.core | ||
|
||
import android.view.Choreographer | ||
|
||
public open class ChoreographerCompat { | ||
|
||
@Deprecated("Use Choreographer.FrameCallback instead") | ||
public abstract class FrameCallback : Choreographer.FrameCallback | ||
} |
172 changes: 0 additions & 172 deletions
172
...native/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactChoreographer.java
This file was deleted.
Oops, something went wrong.
143 changes: 143 additions & 0 deletions
143
...t-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/ReactChoreographer.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
package com.facebook.react.modules.core | ||
|
||
import android.view.Choreographer | ||
import com.facebook.common.logging.FLog | ||
import com.facebook.infer.annotation.Assertions | ||
import com.facebook.react.bridge.UiThreadUtil | ||
import com.facebook.react.common.ReactConstants | ||
import com.facebook.react.common.annotations.VisibleForTesting | ||
import com.facebook.react.internal.ChoreographerProvider | ||
import java.util.ArrayDeque | ||
|
||
/** | ||
* A simple wrapper around Choreographer that allows us to control the order certain callbacks are | ||
* executed within a given frame. The wrapped Choreographer instance will always be the main thread | ||
* one and the API's are safe to use from any thread. | ||
*/ | ||
public class ReactChoreographer private constructor(choreographerProvider: ChoreographerProvider) { | ||
public enum class CallbackType(internal val order: Int) { | ||
/** For use by perf markers that need to happen immediately after draw */ | ||
PERF_MARKERS(0), | ||
/** For use by [com.facebook.react.uimanager.UIManagerModule] */ | ||
DISPATCH_UI(1), | ||
/** For use by [com.facebook.react.animated.NativeAnimatedModule] */ | ||
NATIVE_ANIMATED_MODULE(2), | ||
/** Events that make JS do things. */ | ||
TIMERS_EVENTS(3), | ||
/** | ||
* Event used to trigger the idle callback. Called after all UI work has been dispatched to JS. | ||
*/ | ||
IDLE_EVENT(4) | ||
} | ||
|
||
private var choreographer: ChoreographerProvider.Choreographer? = null | ||
private val callbackQueues: Array<ArrayDeque<Choreographer.FrameCallback>> = | ||
Array(CallbackType.entries.size) { ArrayDeque() } | ||
private var totalCallbacks = 0 | ||
private var hasPostedCallback = false | ||
|
||
private val frameCallback = | ||
Choreographer.FrameCallback { frameTimeNanos -> | ||
synchronized(callbackQueues) { | ||
|
||
// Callbacks run once and are then automatically removed, the callback will | ||
// be posted again from postFrameCallback | ||
hasPostedCallback = false | ||
for (i in callbackQueues.indices) { | ||
val callbackQueue = callbackQueues[i] | ||
val initialLength = callbackQueue.size | ||
for (callback in 0 until initialLength) { | ||
val frameCallback = callbackQueue.pollFirst() | ||
if (frameCallback != null) { | ||
frameCallback.doFrame(frameTimeNanos) | ||
totalCallbacks-- | ||
} else { | ||
FLog.e(ReactConstants.TAG, "Tried to execute non-existent frame callback") | ||
} | ||
} | ||
} | ||
maybeRemoveFrameCallback() | ||
} | ||
} | ||
|
||
init { | ||
UiThreadUtil.runOnUiThread { choreographer = choreographerProvider.getChoreographer() } | ||
} | ||
|
||
public fun postFrameCallback(type: CallbackType, callback: Choreographer.FrameCallback) { | ||
synchronized(callbackQueues) { | ||
callbackQueues[type.order].addLast(callback) | ||
totalCallbacks++ | ||
Assertions.assertCondition(totalCallbacks > 0) | ||
if (!hasPostedCallback) { | ||
if (choreographer == null) { | ||
// Schedule on the main thread, at which point the constructor's async work will have | ||
// completed | ||
UiThreadUtil.runOnUiThread { | ||
synchronized(callbackQueues) { postFrameCallbackOnChoreographer() } | ||
} | ||
} else { | ||
postFrameCallbackOnChoreographer() | ||
} | ||
} | ||
} | ||
} | ||
|
||
public fun removeFrameCallback(type: CallbackType, frameCallback: Choreographer.FrameCallback?) { | ||
synchronized(callbackQueues) { | ||
if (callbackQueues[type.order].removeFirstOccurrence(frameCallback)) { | ||
totalCallbacks-- | ||
maybeRemoveFrameCallback() | ||
} else { | ||
FLog.e(ReactConstants.TAG, "Tried to remove non-existent frame callback") | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* This method writes on mHasPostedCallback and it should be called from another method that has | ||
* the lock on [callbackQueues]. | ||
*/ | ||
private fun postFrameCallbackOnChoreographer() { | ||
choreographer?.postFrameCallback(frameCallback) | ||
hasPostedCallback = true | ||
} | ||
|
||
/** | ||
* This method reads and writes on mHasPostedCallback and it should be called from another method | ||
* that already has the lock on [callbackQueues]. | ||
*/ | ||
private fun maybeRemoveFrameCallback() { | ||
Assertions.assertCondition(totalCallbacks >= 0) | ||
if (totalCallbacks == 0 && hasPostedCallback) { | ||
choreographer?.removeFrameCallback(frameCallback) | ||
hasPostedCallback = false | ||
} | ||
} | ||
|
||
public companion object { | ||
private var choreographer: ReactChoreographer? = null | ||
|
||
@JvmStatic | ||
public fun initialize(choreographerProvider: ChoreographerProvider) { | ||
if (choreographer == null) { | ||
choreographer = ReactChoreographer(choreographerProvider) | ||
} | ||
} | ||
|
||
@JvmStatic | ||
public fun getInstance(): ReactChoreographer = | ||
checkNotNull(choreographer) { "ReactChoreographer needs to be initialized." } | ||
|
||
@VisibleForTesting | ||
internal fun overrideInstanceForTest(instance: ReactChoreographer?): ReactChoreographer? = | ||
choreographer.also { choreographer = instance } | ||
} | ||
} |
Oops, something went wrong.