我应该使用哪个线程在 react-native native ui 组件中调用 uiManager 调用?

Which thread am I supposed to use to call uiManager calls inside a react-native native ui component?

我正在为 Android 构建一个 原生 UI 组件,它使用扩展 ReactRootView.[=25= 的视图]

在我的视图(名为 SyncRootView)的构造函数中,如果我检查线程,我得到 Thread curThread = Thread.current(); // main 所以我们在主线程上。

问题是,如果我尝试 运行 任何 uiManager 调用(例如 uiManager.createView,我会收到该错误:

FATAL EXCEPTION: main
 Process: com.rnexample, PID: 16424
 java.lang.AssertionError
     at com.facebook.infer.annotation.Assertions.assertCondition(Assertions.java:66)
     at com.facebook.react.common.SingleThreadAsserter.assertNow(SingleThreadAsserter.java:27)
     at com.facebook.react.uimanager.ShadowNodeRegistry.getNode(ShadowNodeRegistry.java:67)
     at com.facebook.react.uimanager.UIImplementation.createView(UIImplementation.java:278)
     at com.facebook.react.uimanager.UIManagerModule.createView(UIManagerModule.java:364)
     at com.sudoplz.rnsynchronouslistmanager.Sync.SyncRootView.run(SyncRootView.java:177)
     at android.os.Handler.handleCallback(Handler.java:751)
     at android.os.Handler.dispatchMessage(Handler.java:95)
     at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31)
     at android.os.Looper.loop(Looper.java:154)
     at android.app.ActivityThread.main(ActivityThread.java:6119)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

所以基本上问题是 class 称为 SingleThreadAsserterreact-native 部分,我什至不确定它为什么在那里。 它的 mThread 值设置为 native_module_thread... 因此我得到一个 AssertionError 因为我在主线程上。

如果我尝试 运行 native_module 线程上的那些 uiManager 调用(通过使用 ctx.runOnNativeModulesQueueThread(myRunnable)),起初它似乎有效,但后来(我想一旦模块初始化结束了??)我得到

Tried to enqueue runnable on already finished thread: 'native_modules... dropping Runnable.
02-21 01:55:36.415 17126-17126/com.rnexample W/MessageQueue: Handler (com.facebook.react.bridge.queue.MessageQueueThreadHandler) {bda653f} sending message to a Handler on a dead thread
 java.lang.IllegalStateException: Handler (com.facebook.react.bridge.queue.MessageQueueThreadHandler) {bda653f} sending message to a Handler on a dead thread
     at android.os.MessageQueue.enqueueMessage(MessageQueue.java:543)
     at android.os.Handler.enqueueMessage(Handler.java:643)
     at android.os.Handler.sendMessageAtTime(Handler.java:612)
     at android.os.Handler.sendMessageDelayed(Handler.java:582)
     at android.os.Handler.post(Handler.java:338)
     at com.facebook.react.bridge.queue.MessageQueueThreadImpl.runOnQueue(MessageQueueThreadImpl.java:61)
     at com.facebook.react.bridge.ReactContext.runOnNativeModulesQueueThread(ReactContext.java:287)
     at com.sudoplz.rnsynchronouslistmanager.Sync.SyncRootView.dispatchInUIThread(SyncRootView.java:516)
     at com.sudoplz.rnsynchronouslistmanager.Sync.SyncRootView.runApplication(SyncRootView.java:188)
     at com.sudoplz.rnsynchronouslistmanager.Sync.SyncRootView.<init>(SyncRootView.java:97)
     at com.sudoplz.rnsynchronouslistmanager.Sync.SyncRootView.<init>(SyncRootView.java:61)
     at com.sudoplz.rnsynchronouslistmanager.List.SPView.<init>(SPView.java:20)
     at com.sudoplz.rnsynchronouslistmanager.SynchronousListManager.createViewInstance(SynchronousListManager.java:37)
     at com.sudoplz.rnsynchronouslistmanager.SynchronousListManager.createViewInstance(SynchronousListManager.java:19)
     at com.facebook.react.uimanager.ViewManager.createView(ViewManager.java:44)
     at com.facebook.react.uimanager.NativeViewHierarchyManager.createView(NativeViewHierarchyManager.java:224)
     at com.facebook.react.uimanager.UIViewOperationQueue$CreateViewOperation.execute(UIViewOperationQueue.java:153)
     at com.facebook.react.uimanager.UIViewOperationQueue.run(UIViewOperationQueue.java:813)
     at com.facebook.react.uimanager.UIViewOperationQueue.flushPendingBatches(UIViewOperationQueue.java:926)
     at com.facebook.react.uimanager.UIViewOperationQueue.access00(UIViewOperationQueue.java:47)
     at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:986)
     at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:31)
     at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:136)
     at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback.doFrame(ChoreographerCompat.java:107)
     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:872)
     at android.view.Choreographer.doCallbacks(Choreographer.java:686)
     at android.view.Choreographer.doFrame(Choreographer.java:618)
     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
     at android.os.Handler.handleCallback(Handler.java:751)
     at android.os.Handler.dispatchMessage(Handler.java:95)
     at android.os.Looper.loop(Looper.java:154)
     at android.app.ActivityThread.main(ActivityThread.java:6119)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

有什么想法吗?

我最终这样做了:

在我的 ReactRootView 的构造函数上我做了:

nativeModulesThread = (MessageQueueThreadImpl) ctx.getCatalystInstance().getReactQueueConfiguration().getNativeModulesQueueThread(); 其中 ctx 是每个 UI 本机组件可用的 ReactContext

然后我创建了这个方法:

protected void dispatchInAppropriateThread(Runnable runnable) {
    if (runnable == null) {
        return;
    }

    if (nativeModulesThread.getLooper().getThread().isAlive()) {
        ctx.runOnNativeModulesQueueThread(runnable);
    } else {
        this.post(runnable);
    }
}

所以现在每当我需要 运行 一个 运行nable 我做:

dispatchInAppropriateThread(new Runnable() {
    @Override
    public void run() {
        // do cool stuff
    }
});