Android 列出模块函数,ReactNative之原生模块开发并发布——android篇

前段时间做了个ReactNative的App,发现ReactNative中不少组件并不存在,所以还是需要自己对原生模块进行编写让JS调用,正是因为在这个编写过程中遇到不少问题,发觉了官网文档中许多的不足。所以产生了写一个实践教程的想法,最终有了这么一篇文章。

整篇文章主要以编写一个原生模块为例子,来讲述了我们在编写原生模块所用到的一些知识,并且在整个例子中,配有了完整的实践代码,方便大家理解并调试。除了这些内容,文章还讲述了我们如何将自己编写的原生模块发布到npm上分享给别人使用。希望能够给大家带来帮助,也希望大家将自己编写的原生模块分享出来。

准备工作

我们需要先创建一个ReactNative工程,使用如下命令创建。

1

$ react

native init TestProject

创建好工程之后,我们使用android

studio打开TestProject/android/下的android工程。

之后,点击android studio菜单上的File

——> New ——> New Module,之后选择Android

Library,设置模块名和包名,我的设置如下:

a4c26d1e5885305701be709a3d33442f.png

点击完成之后,我们的安卓项目中就多了个名字为nativemoduleexample模块。

a4c26d1e5885305701be709a3d33442f.png

之后,我们在app工程中的build.gradle文件中的dependencies添加一行compile

project(':nativemoduleexample'),让主工程app依赖我们新创建的Library。

最后,我们还需要让新创建的Library依赖react

native,和上面差不多,只需要在我们新创建的nativemoduleexample下的build.gradle中的dependencies添加一行compile

"com.facebook.react:react-native:+"就行了。

一、编写原生模块代码

####1、创建原生模块,并进行注册

我们首先点击打开前面创建的nativemoduleexample库,在src/main/; border-radius: 5px; border-width: 0.1px;">src/main/java/后面跟上就是前面设置的包名。

在这个目录下,我们首先创建一个原生模块BGNativeExampleModule,它继承于ReactContextBase; border-radius: 5px; border-width: 0.1px;">BGNativeExampleModule。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

package

com.liuchungui.nativemoduleexample;

import

com.facebook.react.bridge.NativeModule;

import

com.facebook.react.bridge.ReactApplicationContext;

import

com.facebook.react.bridge.ReactContext;

import

com.facebook.react.bridge.ReactContextBaseJavaModule;

import

com.facebook.react.bridge.ReactMethod;

import java.lang.String;

public class BGNativeExampleModule

extends ReactContextBaseJavaModule

{

public BGNativeExampleModule(ReactApplicationContext

reactContext) {

super(reactContext);

}

@Override

public String getName() {

return "BGNativeModuleExample";

}

}

其中需要注意的是,模块名前的RCT前缀会被自动移除。例如”RCTBGNativeModuleExample”,在JS中的模块名字仍然是BGNativeModuleExample。

到这一步的时候,是不是就可以访问这个模块了?事实是现在还不能访问,因为我们还需要注册这个模块。

为了注册原生模块,我们首先创建一个BGNativeExamplePackage类,这个类要求实现ReactPackage接口,这个接口有三个方法createNativeModules、createJSModules和createViewManagers。其中,createNativeModules是用来添加原生模块的;createViewManagers是用来添加原生的UI组件;createJSModules暂时没用过,但是看官方的注释,应该是注册我们原生模块中用到的JS模块。

我们这里只需要在createNativeModules方法中添加原生模块,其他两个方法返回空数组就行了,整个package类的代码如下:

package

com.liuchungui.nativemoduleexample;

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.Arrays;

import

java.util.Collections;

import

java.util.List;

public

class BGNativeExamplePackage implements ReactPackage {

@Override

public

List createNativeModules(ReactApplicationContext reactContext)

{

return

Arrays.asList(new NativeModule[]{

new

BGNativeExampleModule(reactContext),

});

}

public

List> createJSModules() {

return

Collections.emptyList();

}

@Override

public

List createViewManagers(ReactApplicationContext reactContext)

{

return

Collections.emptyList();

}

}

最后,这个package需要在MainActivity.; border-radius: 5px; border-width: 0.1px;">android/app/src/main/java/com/testproject/MainActivity.java。

@Override

protected

List getPackages() {

return

Arrays.asList(

new

MainReactPackage(),

new

BGNativeExamplePackage()

);

}

到这个时候,我们终于可以在js中访问我们的原生模块了

import {

NativeModules } from 'react-native';

var

BGNativeModuleExample = NativeModules.BGNativeModuleExample;

console.log(BGNativeModuleExample);

2、为原生模块添加方法

要导出一个方法给JS使用,Java方法需要使用注解@ReactMethod。方法的返回类型必须为void。ReactNative跨语言访问是异步进行的,所以想要给JS返回一个值,唯一的办法是使用回调函数或者发送事件。

import

com.facebook.react.bridge.ReactMethod;

@ReactMethod

public

void testPrint(String name, ReadableMap info) {

Log.i(TAG, name);

Log.i(TAG, info.toString());

}

在JS中,我们如下调用这个方法:

BGNativeModuleExample.testPrint("Jack", {

height:

'1.78m',

weight:

'7kg'

});

3、参数类型

在编写原生模块的时候,我们还需要知道原生Java数据类型和JS数据类型的映射关系:

Boolean

-> Bool

Integer

-> Number

Double

-> Number

Float

-> Number

String

-> String

Callback

-> function

ReadableMap -> Object

ReadableArray -> Array

4、回调函数

原生模块还支持一种特殊的参数——回调函数。它提供了一个函数来把返回值传回给JS。

import

com.facebook.react.bridge.Callback;

@ReactMethod

public

void getNativeClass(Callback callback) {

callback.invoke("BGNativeExampleModule");

}

在JS中,我们可以通过以下方式获取到原生模块的类名:

1

2

3

BGNativeModuleExample.getNativeClass(name => {

console.log("nativeClass: ",

name);

});

5、Promises

原生模块还可以使用promise来简化代码,搭配ES2016(ES7)标准的async/await语法则效果更佳。如果桥接原生方法的最后一个参数是一个Promise,则对应的JS方法就会返回一个Promise对象。

1

2

3

4

5

6

7

8

9

10

import

com.facebook.react.bridge.Promise;

@ReactMethod

public void testPromises(Boolean isResolve,

Promise promise) {

if(isResolve) {

promise.resolve(isResolve.toString());

}

else

{

promise.reject(isResolve.toString());

}

}

JS中如下调用

1

2

3

4

5

6

7

BGNativeModuleExample.testPromises(true)

.then(result => {

console.log("result is ",

result);

})

.catch(result => {

console.log("result = ", result);

});

6、导出常量

我们在getContants方法中导出js所需要使用的常量。

1

2

3

4

5

6

7

@Override

public Map getConstants() {

final

Map constants = new HashMap<>();

constants.put("BGModuleName", "BGNativeModuleExample");

constants.put(TestEventName, TestEventName);

return constants;

}

我们在JS中打印BGModuleName这个常量的值:

1

console.log("BGModuleName const value =

", BGNativeModuleExample.BGModuleName);

7、给JS发送事件

原生模块可以在没有被调用的情况下往JS发送事件通知,最简单的办法是通过RCTDeviceEventEmitter,这可以通过ReactContext获得对应的引用。

在这里,我们为了能够接收到事件,开启了一个定时器,每一秒发送一次事件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

public class BGNativeExampleModule

extends ReactContextBaseJavaModule

{

protected static final String TAG

= BGNativeExampleModule.class.getSimpleName();

private static final String

TestEventName = "TestEventName";

private Timer timer;

public BGNativeExampleModule(final ReactApplicationContext

reactContext) {

super(reactContext);

//开启定时器

TimerTask

task = new TimerTask() {

@Override

public void run() {

//发送事件

WritableMap params = Arguments.createMap();

params.putString("name", "Jack");

reactContext

.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)

.emit(TestEventName, params);

}

};

timer =

new

Timer();

timer.schedule(task, 1000, 1000);

}

}

在JS中,我们这里直接使用DeviceEventEmitter模块来监听事件。

1

2

3

4

//接收事件

DeviceEventEmitter.addListener(BGNativeModuleExample.TestEventName,

info => {

console.log(info);

});

官方文档中,说也可以使用Subscribable

mixin的addListenerOn方法来接收事件,其实它就是对DeviceEventEmitter一种封装。而且,在es6之后,不再支持mixins,所以我们直接使用DeviceEventEmitter接收事件比较好。

8、生命周期

有时候,为了某些目的,我们需要监听ReactNative应用的生命周期。我们可以让原生模块实现LifecycleEventListener接口,然后使用addLifecycleEventListener注册一下监听。

1

2

3

4

5

public BGNativeExampleModule(final ReactApplicationContext

reactContext) {

super(reactContext);

//添加监听

reactContext.addLifecycleEventListener(this);

}

实现LifecycleEventListener接口

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

@Override

public

void

onHostResume() {

Log.i(TAG, "onHostResume");

}

@Override

public

void

onHostPause() {

Log.i(TAG, "onHostPause");

timer.cancel();

}

@Override

public

void

onHostDestroy() {

Log.i(TAG, "onHostDestroy");

timer.cancel();

}

这样,我们就可以监听ReactNative应用的生命周期了。

上面原生代码就编写好了,主要以代码实践为主,弥补官方文档中的一些不足,如果要需要了解更多的原生模块封装的知识,可以参考原生模块,也可以参考官方的源代码。

二、发布上线

建立一个github仓库

在github上创建一个仓库react-native-BGNativeModuleExample,克隆到本地,并且创建一个android文件夹。

1

2

3

$ git

clone

https://github.com/liuchungui/react-native-BGNativeModuleExample.git

$

cd

react-native-BGNativeModuleExample

$ mkdir

android

将Library复制到android文件夹下

我们首先进入前面创建的nativemoduleexample这个Library下,然后将这个文件目录下所有文件copy到react-native-BGNativeModuleExample/android目录下。

$ cp -R

android/nativemoduleexample/*

~/github/react-native-BGNativeModuleExample/android

发布到npm

这里请参考我前面写的ReactNative之原生模块开发并发布——iOS篇中的发布到npm那一节的内容,当然如果你和我一样前面已经发布了1.0.0,只需要将package.json修改一个版本就好了,我这里修改为2.0.0,然后使用下面命令发布。

$ npm

publish

+

react-native-nativemodule-example@2.0.0

这样,我们就成功发布到了npmjs.org。

三、添加Example,测试是否可用,添加README

请点击查看ReactNative之原生模块开发并发布——iOS篇中的添加Example,测试是否可用,添加README这一部分内容,基本上一样的。

参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值