Android端接口

RN端向Android侧通信可以通过Android侧的接口来实现。

实现接口

Android侧的接口都需要继承ReactContextBaseJavaModule类,如下:

class MyModule extends ReactContextBaseJavaModule {
    @NonNull
    @Override
    public String getName() { return "MyModule"; } // 1
    
    @ReactMethod
    public void handleMessage(String msg, Promise pro) { } // 2
}
  1. 这些类统一都需要实现getName函数,这个函数的用途是返回原生模块代码的名称以供RN模块调用,在RN侧使用这个名称来调用在这个类中定义的函数。

  2. 想要调用的函数必须要用@ReactMethod关键字将其注释为一个React函数才能在RN侧被调用。

    并且这些函数不能有返回值,因为被调用的原生代码是异步执行的。

    那么如果我们想要执行完原生的逻辑后想要得到返回值该怎么办呢?我们可以使用异步的方法来做,例如回调函数Promiseasync等。

    值得注意的是,即使正确调用了回调函数,这些回调函数也不会立即这些,因为混合开发中的桥接机制是异步的,中间应该用了一个类似于消息队列的机制。

注册模块

在 Android侧要做的最后一件事就是注册这个模块。为此开发者需要实现一个React包管理类。这个类需要继承ReactPackage类。我们需要在这个ReactPackage类的createNativeModules方法中添加我们实现好的模块。如果模块没有被注册,它也无法在 JavaScript 中被访问到。

class MyPackage extends ReactPackage {
	@Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        List<NativeModule> modules = new ArrayList<>();
        modules.add(new MyModule(reactContext));
        // 这个包管理类的List里可以管理多个module
        return modules;
    }
}

这个ReactPackage类将在MainApplication.javagetPackages方法中被创建一个实例。

protected List<ReactPackage> getPackages() {
  @SuppressWarnings("UnnecessaryLocalVariable")
  List<ReactPackage> packages = new PackageList(this).getPackages();
  packages.add(new MyPackage()); // <-- 添加这一行,类名替换成你的Package类的名字 name.
  return packages;
}

RN端使用

handleMessage(string msg) {
    let { NativeModules } = require('react-native');
    NativeModules.handleMessage(msg).then(() => { });
}

注意:如果我们更改了Android项目中的代码,我们需要重新编译Android项目,项目在编译时会中断cmd窗口的监听程序,我们需要再次打开一个cmd运行’react-native start’ 重新开始监听。

跨语言常量

同样的我们可以在Android端通过实现名为getConstants的成员函数来将某些常量暴露给RN侧,这个方法在Android和RN侧需要保持某些常量的一致的时候会有用处。如下:

@Override
public Map<String, Object> getContants() { return MyMap; }

Android侧主动向RN侧发消息

当Android侧需要主动向RN侧发消息时,可以使用消息机制。

// Android侧
MyContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(eventName, msg);
// rn侧
DeviceEventEmitter.addListener(eventName, (msg) => { })

注意:使用getJSModule必须要有一个ReactApplicationContext的实例,那么,我们如何获得这个ReactApplication的实例呢?

这里就需要提出一个开发的建议:尽管getJSModule可以在任何位置使用,但是还是建议在ReactContextBaseJavaModule中使用,因为MyModule在创建和注册的时候——createNativeModule 会传递一个ReactApplicationContext,所以创建MyModule的时候可以让构造函数中带上这个参数,这样我们就可以在MyModule中使用ReactApplicationContext了。

Android与RN界面的切换

同样的,我们可以让原生代码初始化一个视图,并且让这个视图获得焦点,这样就实现了RN和原生界面的切换.

初始界面的界定

Android应用初始界面在AndroidManifest.xml文件中进行设置。文件中含有“intent-filter”字段所在的Activity就是默认启动的第一个Activity。

我们可以观察一个项目中被intent-filter标注的Activity,如果这个Activity继承的是ReactActiity,那么这个项目的初始界面就是一个RN界面。

RN向Android的跳转

RN向Android的跳转很简单,与上面接口的实现很类似,只要在需要跳转的时候调用Android端的接口,然后在这个接口中创建intent执行startActivity即可。(//TODO: 可以直接start一个Fragment吗?)

关键在于Android端回到RN端,如果Android不需要传递消息,那么在Android的Activity执行了finish之后就可以回到RN界面,如果需要回传消息,那么就需要在自己实现的ReactContextBaseJavaModule类中实现onActivityResult(),解析出传回来的消息后再使用Promise机制或者消息机制将消息传递给RN端。

Android向原生的跳转

如果初始界面为Android的界面,那么就需要实现从Android向原生的跳转。

Android向RN的跳转不是直接跳转到RN,而是跳转到RN在Android侧的界面容器中。我们需要在Android注册一个ReactActivity假设叫MyReactActivity,当我们需要进行跳转的时候,startActivity就是要启动这个MyReactActivity。

class MyReactActivity extends ReactActivity { }

那么MyReactActivity如何映射到RN界面呢,这就需要在RN端进行注册。如下所示:

// APP.js
import MyComponent from './index.js';
AppRegistry.registerComponent('MyReactActivity', () => MyComponent);

Logo

智屏生态联盟致力于大屏生态发展,利用大屏快应用技术降低开发者开发、发布大屏应用门槛

更多推荐