React Native自己已經提供不少可用的模塊和組件,有一部分咱們須要的模塊和組件仍然沒法直接提供,須要藉助原生的代碼來提供。封裝原生模塊和視圖導出使用,也可讓React Native擁有android和ios平臺的強大生態鏈和使用衆多第三方類庫。java
如下以支付寶支付模塊爲實例react
AlipayModule.javaandroid
// 模塊繼承自ReactContextBaseJavaModule
public class AlipayModule extends ReactContextBaseJavaModule {
// 默認構造方法
public AlipayModule(ReactApplicationContext reactContext) {
super(reactContext);
}
// 模塊名
@Override
public String getName() {
return "AlipayModule";
}
// 添加@ReactMethod註解導出方法
// promise需放在最後
@ReactMethod
public void pay(final String orderInfo, final Promise promise) {
Runnable runnable = new Runnable() {
@Override
public void run() {
PayTask alipay = new PayTask(getCurrentActivity());
Map<String, String> result = alipay.payV2(orderInfo,true);
Log.i("AlipayModule", "resultStatus: " + result.get("resultStatus"));
if ("9000".equals(result.get("resultStatus"))) {
promise.resolve(true);
} else {
promise.resolve(false);
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
複製代碼
MyReactPackage.javaios
// 實現ReactPackage接口
// 用於註冊導出的模塊和視圖
public class MyReactPackage implements ReactPackage {
// 原生模塊註冊
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(
new AlipayModule(reactContext)
);
}
// 原生視圖註冊
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList();
}
}
複製代碼
在MainApplication getPackages方法中添加new MyReactPackage()
react-native
AlipayModule.hpromise
#import <React/RCTBridgeModule.h>
@interface AlipayModule : NSObject<RCTBridgeModule>
@end
複製代碼
AlipayModule.mbash
#import "AlipayModule.h"
#import <AlipaySDK/AlipaySDK.h>
@interface AlipayModule()
@end
@implementation AlipayModule
// 添加宏,導出模塊
RCT_EXPORT_MODULE();
// 使用宏,導出方法,resolve和reject爲promise方法
RCT_EXPORT_METHOD(pay: (NSString *) orderInfo resolver: (RCTPromiseResolveBlock) resolve rejecter:(RCTPromiseRejectBlock) reject)
{
[[AlipaySDK defaultService] payOrder:orderInfo fromScheme:@"本app的schema" callback:^(NSDictionary *resultDic)
{
if ([@"9000" isEqualToString: [resultDic valueForKey:@"resultStatus"]]) {
resolve(@(YES));
} else {
resolve(@(NO));
}
}];
}
@end
複製代碼
Alipay.tsapp
import {NativeModules} from 'react-native';
export interface Alipay {
pay(orderInfo: string): Promise<boolean>;
}
export const Alipay = NativeModules.AlipayModule as Alipay;
複製代碼
import Alipay from './Alipay';
try {
const result = await Alipay.pay(orderInfo);
if (result) console.log('支付成功');
} catch(e) {
console.error(e);
}
複製代碼
原生模塊導出相對而言仍是很是簡單的,在上面支付寶支付的實例中演示了導出一個簡單的模塊和promise在原生代碼中的注入和在js層的使用。ide
js中調用模塊代碼,模塊中直接導出便可,有時候咱們也會須要在原生代碼中去調用js的代碼,例如作事件通知等。ui
事件名爲js層監聽的名字,值能夠爲int、float等,與原生方法一直
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("事件名", 值);
複製代碼
const listener = DeviceEventEmitter.addListener('事件名',
data => console.log('android調用', data));
// 調用完成移除監聽
listener.remove();
複製代碼
模塊.h文件
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
// 修改.h中NSObject爲RCTEventEmitter
@interface XXXModule : RCTEventEmitter<RCTBridgeModule>
@end
複製代碼
模塊.m文件
// 添加支持事件名
- (NSArray<NSString *> *)supportedEvents
{
return @[@"event1", @"event2"];
}
// 事件發送
// float body [NSNumber numberWithFloat:num]
[self sendEventWithName:@"event1" body:body];
複製代碼
// 獲取模塊監聽者
// XXXModule爲模塊名稱,與導出的名字一致
const eventEmitter = new NativeEventEmitter(NativeModules.XXXModule);
const listener = eventEmitter.addListener('事件名',
data => console.log('ios調用', data));
// 監聽完成後移除
listener.remove();
複製代碼
ios和android發送事件封裝方法不同,在js層監聽方法也不同,因此須要注意平臺,通常事件是在耗時操做過程當中監聽,在開始時候開始監聽,在結束後應立刻移除監聽。