只有一个回调可以注册到本机模块中的函数反应本机错误

Only one callback may be registered to a function in a native module react native error

我最近向我添加了一个 android 本机模块,它侦听来自系统的时区和时间更改广播,并允许应用程序执行一些操作。本机模块看起来像这样

public class TimezoneHandlerModule extends ReactContextBaseJavaModule {
    private final Context context;
    private final TimezoneChangeBroadcastReceiver timezoneChangeBroadcastReceiver;
    private Callback onTimezoneChangeCallback;

    public TimezoneHandlerModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.context = reactContext;
        this.timezoneChangeBroadcastReceiver = new TimezoneChangeBroadcastReceiver();
    }

    private void registerForTimezoneChangeHandler() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
        getReactApplicationContext().registerReceiver(timezoneChangeBroadcastReceiver, intentFilter);
    }

    private void unregisterTimezoneChangeHandler() {
        getReactApplicationContext().unregisterReceiver(timezoneChangeBroadcastReceiver);
    }

    public void setOnTimezoneChangeCallback(Callback onTimezoneChangeCallback) {
        this.onTimezoneChangeCallback = onTimezoneChangeCallback;
    }

    /**
     * @return the name of this module. This will be the name used to {@code require()} this module
     * from javascript.
     */
    @Override
    public String getName() {
        return "TimezoneHandler";
    }

    @ReactMethod
    public void start(Callback onChange) {
        Log.d(getName(), "Starting the timezone change handler");
        this.registerForTimezoneChangeHandler();
        this.setOnTimezoneChangeCallback(onChange);
    }

    @ReactMethod
    public void stop() {
        Log.d(getName(), "Stopping the timezone change handler");
        this.unregisterTimezoneChangeHandler();
    }

    private class TimezoneChangeBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(getName(), "Received broadcast for timezone/time change " + intent.getAction());
            final String action = intent.getAction();

            if (action.equals(Intent.ACTION_TIME_CHANGED) || action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
                TimezoneHandlerModule.this.onTimezoneChangeCallback.invoke();
            }
        }
    }
}

公开了两个 React 方法 startstopstart 将函数作为参数,每当接收到时区更改或时间更改的广播时调用该函数。连接本机模块并在模拟器中启动应用程序后,我打开 Settings 并更改时区,可以看到打印了相关日志。

11-24 17:07:21.837 1597-1597/com.xyz D/TimezoneHandler: Received broadcast for timezone/time change
11-24 17:07:21.837 1597-1907/com.xyz I/ReactNativeJS: Detected timezone change

当我再次更改时区时,我在 logcat 输出中看到以下错误

1-24 17:22:42.356 1597-1597/com.galarmapp D/TimezoneHandler: Received broadcast for timezone/time change
11-24 17:22:42.365 1597-1907/com.galarmapp E/ReactNativeJS: The callback start() exists in module TimezoneHandler, but only one callback may be registered to a function in a native module.
11-24 17:22:42.367 1597-1908/com.galarmapp E/unknown:React: The callback start() exists in module TimezoneHandler, but only one callback may be registered to a function in a native module., stack:
                                                            __invokeCallback@12814:10
                                                            <unknown>@12685:24
                                                            guard@12604:3
                                                            invokeCallbackAndReturnFlushedQueue@12684:6

从错误消息来看,似乎我正在尝试将单独的回调附加到 start 函数,但我没有做任何此类事情。我在顶级组件的 componentWillMount 中调用 start 方法,并确认它没有被调用两次。我看到其他人在尝试不同的事情时也看到了这个错误,但仍然不明白问题背后的原因。

如果您有任何见解,请分享。

根据文档 http://facebook.github.io/react-native/docs/native-modules-android.html#callbacks - "A native module is supposed to invoke its callback only once. It can, however, store the callback and invoke it later." 一旦您对回调执行了 invoke() 操作,就无法再次使用它。

通过将事件发送到 javascript 可以更好地解决这种时区更改的特殊用例。请参阅此文档 http://facebook.github.io/react-native/docs/native-modules-android.html#sending-events-to-javascript