1. 原生模块基础篇

1.1. 创建原生库

可以手动一步一步创建原生库,也可以直接使用工具

1.1.1. 手动创建原生库

创建 Example 工程

cd <react-native-example-module>
npm init
mkdir ios
mkdir android

创建 Example 工程

react-native init Example
cd <react-native-example-module>/Example
npm install

创建 iOS 原生模块

cd <react-native-example-module>/Example

创建原生模块

react-native new-library --name RNExampleModule

拷贝文件到 ios 目录

cp -a Libraries/RNExampleModule/*.{h,m,xcodeproj} ../ios/
cp Libraries/RNExampleModule/*.js ../

删除临时文件

rm -rf Libraries/RNExampleModule

创建 Android 原生模块

cd <react-native-example-module>/Example

打开 Example Android 工程

studio android

创建模块

File > New > New Module > 选择 Android Library > Next >
Application/Library Name 输入模块名:Example Module,
Module name 输入模块名:react-native-example-module,
Package name 输入包名:im.shimo.baidumjt,
Minimum SDK:API 16
> Finish

build.gradle 做如下修改

  • 由于 RN 用的老版本的 Gradle,不支持最新的语法。所以 build.gradle 中的 implementation api 要换成 compile,
  • compileSdkVersion 26
  • buildToolsVersion "26.0.2"
  • dependencies 添加 compile 'com.facebook.react:react-native:+'

创建基础的 Module 和 Package 文件。必须要有,否则 link 找不到模块。

拷贝 Android 模块到 android 目录

cp -a android/react-native-example-module/* ../android

AndroidStudio 按下面步骤删除刚创建的模块:

File > Project Structure > 选择 react-native-example-module,点上面的 - 号

删除临时文件

rm -rf android/react-native-example-module
Questions

Q: Could not find common.jar

修改 Gradle Scripts --->build.gradle(Project:项目名)--->allprojects{}如下:

repositories {
        maven{url"https://maven.google.com"}
        jcenter()
        maven{url 'https://jitpack.io'}
}

原生模块 link 到 Example 工程。

适用于 npm5 以下

cd <react-native-example-module>/Example
  1. package.jsondependencies 添加 "react-native-example-module": "../"
  2. npm install

安装原生库到 Example 工程

react-native link

然后在 node_modules/react-native-example-module/ 目录下写原生库代码

写好后再拷贝到工程目录

cp -a node_modules/react-native-example-module/ios/* ../ios/
cp -a node_modules/react-native-example-module/android/* ../android/
cp node_modules/react-native-example-module/*.js ../

适用于 npm5 及以上

cd <react-native-example-module>/Example
npm i ../
react-native link

由于 Example 工程依赖的 react-native-example-module 用的软链接,在上级目录下,所以 Xcode 的 Header Search Paths 需要添加 $(SRCROOT)/../Example/node_modules/react-native/React non-recursive

之后就可以直接在 Example 工程中写原生模块了,相比方法一,不用移动代码。

[有可能会报下面的错]:

  1. error: bundling failed: "Unable to resolve module react

是因为运行 npm i ../ 会创建从 ../node_modules/react-native-example-module/ 的软链接。react 查找路径有可能会出错,需要在 目录安装 react

cd <react-native-example-module>
npm i --no-save react@16.2.0

参考 manual-linking 手动添加依赖

Header Search Paths 添加 $(SRCROOT)/../../ios non-recursive

然后直接在 Example 中写原生库

1.1.2. react-native-create-library 创建原生模块

安装

npm install -g react-native-create-library

使用

以创建 react-native-key-command 模块为例

创建原生模块

react-native-create-library --package-identifier im.shimo.keycommand --platforms ios,android KeyCommand
mv KeyCommand react-native-key-command

创建 Example 工程

cd react-native-key-command
react-native init Example
cd Example
npm install

安装 react-native-key-command 到 Example 工程,参考 Link 方法二 (推荐)

Questions

模块的 AndroidManifest.xml 会报 URI is not registered 错误

试了很多方法,都修不了,但是不影响使用

References

1.1.3. react-native-create-bridge 创建原生模块 (不推荐)

生成的原生模块直接在 RN 主工程里面,不是主工程通过 npm 方式引入。不推荐

References

1.2. iOS 原生模块

1.2.1. UI 库

类名就是 Javascript 中访问的名字

1.2.2. Module

  • 定义个实现 RCTBridgeModule 协议的 Manager
  • Manager 用宏 RCT_EXPORT_MODULE() 添加一个参数用来指定在Javascript中访问这个模块的名字
  • Manager 用宏 RCT_EXPORT_METHOD() 声明要给Javascript导出的方法
  • - (NSDictionary *)constantsToExport 导出常量

1.2.3. 给Javascript发送事件

1.2.4. 添加 cocoapods 依赖

先生成 xcodeproj 工程

pod try AFNetworking

[注意] 并不是对所有 cocoapods 库都支持 pod try

再把依赖工程导入主工程,然后写 Module

1.2.5. 注意事项

  • 回调必须要以 on 开头

1.2.6. References

1.3. Android 原生模块

1.3.1. 普通模块

为 js 提供方法

定义继承 ReactContextBaseJavaModule 的 Module 类

定义模块名

@Override
public String getName() {
  return "ToastAndroid";
}

添加属性

@ReactProp@ReactPropGroup

添加方法

@ReactMethod
public void show(String message, int duration) {
  Toast.makeText(getReactApplicationContext(), message, duration).show();
}

方法中的参数和返回传不能用 Map,需要用 ReadableMap 或者 WritableMap

  • WritableMap 一般是用于从原生传给 RN 的数据。接口,对应实现 ReadableNativeMap
  • ReadableMap 一般是用于 RN 传向原生的数据。接口,对应实现 WritableNativeMap

导出常量

/**
 * @return a map of constants this module exports to JS. Supports JSON types.
 */
public @Nullable Map<String, Object> getConstants() {
  return null;
}

1.3.2. ViewManager 创建 UI 组件

为 js 提供组件,管理组件,ReactShadowNode 管理组件属性

  • createViewInstance 创建视图
  • @ReactProp @ReactPropGroup 导出视图属性的设置方法

1.3.3. Package 注册模块、UI 组件

定义实际接口 ReactPackage 的 Package 类

createNativeModules 方法中添加 Module

@Override
public List<NativeModule> createNativeModules(
                            ReactApplicationContext reactContext) {
  List<NativeModule> modules = new ArrayList<>();
  modules.add(new ToastModule(reactContext));
  return modules;
}

createViewManagers 方法添加 UI 组件

@Override
public List<ViewManager> createViewManagers(
                          ReactApplicationContext reactContext) {
  return Arrays.<ViewManager>asList(
    new ReactImageManager()
  );
}

ReactShadowNode 添加修改布局的方法

MainApplication.java 中添加 Package

protected List<ReactPackage> getPackages() {
    return Arrays.<ReactPackage>asList(
            new MainReactPackage(),
            new AnExampleReactPackage()); // <-- 添加这一行,类名替换成你的Package类的名字.
}

1.3.4. 发送事件到JavaScript

RN JS 层通过 NativeEventEmitter 接收原生事件

1.3.5. 添加 Maven 依赖

build.gradle 中添加 Maven 依赖,再写 Module ViewManager Package 就可以了

1.3.6. References

results matching ""

    No results matching ""