React Native 中的原生模块:函数返回“未定义”

问题描述

所以,我正在练习用 Java 制作原生模块,这些模块可以将函数暴露给 React Native 的 JavaScript 代码。为此,我决定使用一个简单的演示数学库。我的代码如下。

MathOpsModule.java

package com.mb_rn_poc;

import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class MathOpsModule extends ReactContextBaseJavaModule {

  @Override
  public String getName() {
    return "MathOps"; // Name of the Native Modules.
  }

  @ReactMethod
  public int add(int a,int b) {
    return (a + b);
  }
}

MathOpsPackage.java

package com.mb_rn_poc;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MathOpsPackage implements ReactPackage {

@Override
public List<ViewManager> createViewManagers(
  ReactApplicationContext reactContext
) {
    return Collections.emptyList();
}

@Override
public List<NativeModule> createNativeModules(
      ReactApplicationContext reactContext
) {
    List<NativeModule> modules = new ArrayList<>();
    // Register the MathOps module
    modules.add(new MathOpsModule());
    return modules;
  }
}

MainApplication.java

package com.mb_rn_poc;

import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.soLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost =
      new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          // Packages that cannot be autolinked yet can be added manually here,for example:
          // packages.add(new MyReactNativePackage());
          packages.add(new MathOpsPackage());
          return packages;
        }

        @Override
        protected String getJSMainModuleName() {
          return "index";
        }
      };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this,/* native exopackage */ false);
    initializeflipper(this,getReactNativeHost().getReactInstanceManager());
  }

  /**
   * Loads Flipper in React Native templates. Call this in the onCreate method with something like
   * initializeflipper(this,getReactNativeHost().getReactInstanceManager());
   *
   * @param context
   * @param reactInstanceManager
   */
  private static void initializeflipper(
      Context context,ReactInstanceManager reactInstanceManager) {
    if (BuildConfig.DEBUG) {
      try {
        /*
         We use reflection here to pick up the class that initializes Flipper,since Flipper library is not available in release mode
        */
        Class<?> aClass = Class.forName("com.mb_rn_poc.ReactNativeFlipper");
        aClass
            .getmethod("initializeflipper",Context.class,ReactInstanceManager.class)
            .invoke(null,context,reactInstanceManager);
      } catch (ClassNotFoundException e) {
        e.printstacktrace();
      } catch (NoSuchMethodException e) {
        e.printstacktrace();
      } catch (illegalaccessexception e) {
        e.printstacktrace();
      } catch (InvocationTargetException e) {
        e.printstacktrace();
      }
    }
  }
}

现在,在 React Native 方面,我有这两个文件 -

MathOps.js

import { NativeModules } from 'react-native';

const MathOps = NativeModules.MathOps;

export const add = (a,b) => {
    return MathOps.add(a,b);
}

MainApp.js

import React,{ useEffect,useState } from 'react';
import { SafeAreaView,Text,View } from 'react-native';
import { add } from "./NativeWrapper/MathOps";

const MainApp = () => {

    const [state,setState] = useState(0);

    useEffect(() => {
        let sum = add(10,12);
        console.log({ sum });
        setState(sum);

    },[])

    return (
        <SafeAreaView>
            <View>
                <Text>
                    {state}
                </Text>
            </View>
        </SafeAreaView>
    );
}

export default MainApp;

问题是,add 函数返回 undefined。因此,屏幕上不会打印任何内容。知道我可能做错了什么吗?

解决方法

不确定这是什么问题,但有一个解决方法 - 使用回调,如 https://reactnative.dev/docs/native-modules-android 中所述。我做了以下修改-

@ReactMethod
public void add(Double a,Double b,Callback cb) {
    Double sum = a + b;
    cb.invoke(sum);
}
import { /* ... */ NativeModules } from 'react-native';
const { MathModule } = NativeModules;

// ...
// ...

MathModule.add(10,20,(sum) => {
    alert(sum);
})

它按照我的预期运行 - 提醒“30”。