ReactNative开发环境搭建
[TOC]
概述
有时候 App 需要访问平台 API,但 React Native 可能还没有相应的模块包装;或者你需要复用一些 Java 代码,而不是用 Javascript 重新实现一遍;又或者你需要实现某些高性能的、多线程的代码,譬如图片处理、数据库、或者各种高级扩展等等。
我们把 React Native 设计为可以在其基础上编写真正的原生代码,并且可以访问平台所有的能力。这是一个相对高级的特性,我们并不认为它应当在日常开发的过程中经常出现,但具备这样的能力是很重要的。如果 React Native 还不支持某个你需要的原生特性,你应当可以自己实现该特性的封装。
开启 Gradle Daemon
我们建议开启Gradle Daemon来加速 Java 代码编译。
Toast 模块
本向导会用Toast作为例子。假设我们希望可以从 Javascript 发起一个 Toast 消息(一种会在屏幕下方弹出、保持一段时间的消息通知)。
我们首先来创建一个原生模块。一个原生模块是一个继承了ReactContextBaseJavaModule的 Java 类,它可以实现一些 JavaScript 所需的功能。我们这里的目标是可以在 JavaScript 里写ToastExample.show(‘Awesome’, ToastExample.SHORT);,来调起一个短暂的 Toast 通知。
创建一个新的 Java 类并命名为ToastModule.java,放置到android/app/src/main/java/com/your-app-name/目录下,其具体代码如下:
1 | public class ToastModule extends ReactContextBaseJavaModule { |
ReactContextBaseJavaModule要求派生类实现getName方法。这个函数用于返回一个字符串名字,这个名字在 JavaScript 端标记这个模块。这里我们把这个模块叫做ToastExample,这样就可以在 JavaScript 中通过NativeModules.ToastExample访问到这个模块。译注:RN 已经内置了一个名为 ToastAndroid 的模块,所以在练习时请勿使用 ToastAndroid 的名字,否则运行时会报错名字冲突!
一个可选的方法getContants返回了需要导出给 JavaScript 使用的常量。它并不一定需要实现,但在定义一些可以被 JavaScript 同步访问到的预定义的值时非常有用。
1 | @Override |
要导出一个方法给 JavaScript 使用,Java 方法需要使用注解@ReactMethod。方法的返回类型必须为void。React Native 的跨语言访问是异步进行的,所以想要给 JavaScript 返回一个值的唯一办法是使用回调函数或者发送事件(参见下文的描述)。
1 | @ReactMethod |
参数类型
下面的参数类型在@ReactMethod注明的方法中,会被直接映射到它们对应的 JavaScript 类型。
1 | Boolean -> Bool |
参阅ReadableMap和ReadableArray。
注册模块
在 Java 这边要做的最后一件事就是注册这个模块。我们需要在应用的 Package 类的createNativeModules方法中添加这个模块。如果模块没有被注册,它也无法在 JavaScript 中被访问到。
创建一个新的 Java 类并命名为CustomToastPackage.java,放置到android/app/src/main/java/com/your-app-name/目录下,其具体代码如下:
1 | public class CustomToastPackage implements ReactPackage { |
这个 package 需要在MainApplication.java文件的getPackages方法中提供。这个文件位于你的 react-native 应用文件夹的 android 目录中。具体路径是: android/app/src/main/java/com/your-app-name/MainApplication.java.
为了让你的功能从 JavaScript 端访问起来更为方便,通常我们都会把原生模块封装成一个 JavaScript 模块。这不是必须的,但省下了每次都从NativeModules中获取对应模块的步骤。这个 JS 文件也可以用于添加一些其他 JavaScript 端实现的功能。
1 | / ToastExample.js |