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

Var*_*pta 7 react-native react-native-android

我最近添加了一个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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

两个反应的方法被暴露start和stop.start将函数作为参数,每当接收到时区改变或时间改变的广播时调用该参数.在连接本机模块并在模拟器中启动应用程序后,我打开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
Run Code Online (Sandbox Code Playgroud)

当我再次更改时区时,我在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
Run Code Online (Sandbox Code Playgroud)

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

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

age*_*unt 9

根据文档http://facebook.github.io/react-native/docs/native-modules-android.html#callbacks - "本机模块应该只调用一次它的回调.但是,它可以存储回调并稍后调用它." 在回调上完成invoke()后,就无法再次使用它.

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