react native 官网上将原生模块和原生UI组件分开讲,我当时是有些懵的,不知道这两者有何区别,后来发现,其实两个的区别就是原生UI组件需要渲染视图,而原生模块不用。所以两者所继承的模块还是有所区别的。
有时候需要访问平台API,但是react native 没有为我们包装相应的模块,这个时候就需要我们自己去封装了。虽然github上也已经有很多人做了许多了,基本够我们自己用的,但是基本的原理和实现过程还是要懂的。
下面就参照官网上的Toast例子去实现一遍。最后结果: 点击按钮文字后,android底部弹出提示并停留一段时间。
首先要创建一个原生模块:ToastModule.java
原生模块需要继承的是ReactContextBaseJavaModule的Java类,它可以实现一些JavaScript所需的功能。我们这里的目标是可以在JavaScript里写ToastAndroid.show('一定要出来', ToastAndroid.SHORT);,来调起一个Toast通知。
ReactContextBaseJavaModule要求派生类实现getName方法。这个函数用于返回一个字符串名字,这个名字在JavaScript端标记这个模块。这里我们把这个模块叫做ToastAndroidContent,这样就可以在JavaScript中通过React.NativeModules.ToastAndroidContent访问到这个模块。
译注:模块名前的RCT前缀会被自动移除。所以如果返回的字符串为"RCTToastAndroidContent",在JavaScript端依然通过React.NativeModules.ToastAndroidContent访问到这个模块。
一个可选的方法getContants返回了需要导出给JavaScript使用的常量。它并不一定需要实现,但在定义一些可以被JavaScript同步访问到的预定义的值时非常有用。
要导出一个方法给JavaScript使用,Java方法需要使用注解@ReactMethod。方法的返回类型必须为void。React Native的跨语言访问是异步进行的,所以想要给JavaScript返回一个值的唯一办法是使用回调函数或者发送事件。
这里在调用show方法时,就可以将要显示的内容传过来,然后显示。
参数类型:
下面的参数类型在@ReactMethod注明的方法中,会被直接映射到它们对应的JavaScript类型。
注册模块:
模块已经完成了,现在在java这边就只需要把这个模块注册到NativeModule中去了。
新建ToastPackage类,继承 ReactPackage接口,同时需要实现该接口的三个函数,分别是:createJSModules、createViewManagers、createNativeModules。在这里createViewManagers和createJSModules返回的都是空集合,而createNativeModules中则是modules的集合。
代码如下:
package com.reactnativeproject;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
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;
/**
* Created by createdit on 17/2/9.
*/
public class ToastPackage implements ReactPackage {
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new ToastModule(reactContext));
return modules;
}
}
这就注册完毕了。java这边的就完成了,在react native端就可以调用了。
在 reactNative中用时先从 NativeModules中取到,NativeModules是react-native中的,所以记得在 react native 中import进来。
这其实也是react native向原生传值的一种方法,我们可以用js传参给原生,同时也可以回调,将参数回传给js。而参数的类型也可以复杂化。
原生模块其实就是react native 调用原生方法的方法。