React Native 模块 Native 模块封装

React Native 作为跨平台开发框架,在移动开发中使用越来越普及,同时还有着众多的社区支持。除了内置的组件和 API,开发者还可以通过封装 Native 模块,利用 Native 的强大功能来扩展 React Native 的使用能力。本文将介绍如何封装 Native 模块,并提供详细的示例代码。

Native 模块介绍

在 React Native 中,我们通常使用 JavaScript 编写应用程序的逻辑,然后使用 Bridge 将其发送到 Native 代码中去执行,最终显示在屏幕上。而 Native 模块则是一种 Java 或 Objective-C 类或模块,通过 Bridge 向 JavaScript 暴露方法,使得 JavaScript 可以调用 Native 代码来执行相关操作。

封装 Native 模块

假设我们现在需要一个 Native 模块来获取设备信息,我们可以按如下步骤进行封装。

Android 封装步骤

  1. 创建一个 Java 类来定义 Native 模块:
public class DeviceInfoModule extends ReactContextBaseJavaModule {
  private static final String TAG = "DeviceInfoModule";
  private static final String NAME = "DeviceInfo";

  public DeviceInfoModule(ReactApplicationContext reactContext) {
    super(reactContext);
  }

  @Override
  public String getName() {
    return NAME;
  }

  @ReactMethod
  public void getDeviceInfo(Promise promise) {
    try {
      WritableMap map = Arguments.createMap();
      map.putString("brand", Build.BRAND);
      map.putString("model", Build.MODEL);
      map.putString("os", Build.VERSION.RELEASE);
      promise.resolve(map);
    } catch (Exception e) {
      promise.reject(e);
    }
  }
}

这是一个简单的 Java 类,它继承了 ReactContextBaseJavaModule 类,并且实现了 getName()@ReactMethod 注解。其中,getName() 方法用于定义该模块的名称,@ReactMethod 注解表示该方法暴露给 JavaScript 端调用。

  1. 创建一个 ReactPackage 类来注册 Native 模块:
public class DeviceInfoPackage implements ReactPackage {
  @Override
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();
    modules.add(new DeviceInfoModule(reactContext));
    return modules;
  }

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }
}

这个类实现了 ReactPackage 类,并且覆盖了其中的 createNativeModules() 方法。在这个方法里,我们可以添加上面创建的 Native 模块。

  1. MainApplication.java 中注册刚刚创建的 Package:
@Override
protected List<ReactPackage> getPackages() {
  return Arrays.asList(
      new MainReactPackage(),
      new DeviceInfoPackage()
  );
}
  1. 在 JavaScript 端调用 Native 模块:
import { NativeModules } from 'react-native';

const { DeviceInfo } = NativeModules;

DeviceInfo.getDeviceInfo().then(result => {
  console.log(result); // { brand: 'xx', model: 'xx', os: 'x.x.x' }
}).catch(error => {
  console.log(error);
});

在 JavaScript 文件中,我们通过 import 关键字来引用刚刚创建的 Native 模块。然后通过 NativeModules 对象来获取这个模块,最后我们可以使用 getDeviceInfo() 方法来获取设备信息。在这个方法中,我们使用了 Promise 对象来处理异步操作,通过 resolve()reject() 方法来传递结果或错误信息。

iOS 封装步骤

  1. 创建一个 Objective-C 类来定义 Native 模块:
#import "React/RCTBridgeModule.h"

@interface DeviceInfoModule : NSObject <RCTBridgeModule>
@end

@implementation DeviceInfoModule

RCT_EXPORT_MODULE(DeviceInfo);

RCT_EXPORT_METHOD(getDeviceInfo: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
  NSMutableDictionary *dictionary = [NSMutableDictionary new];
  [dictionary setObject:[[UIDevice currentDevice] name] forKey:@"name"];
  [dictionary setObject:[[UIDevice currentDevice] systemName] forKey:@"systemName"];
  [dictionary setObject:[[UIDevice currentDevice] systemVersion] forKey:@"systemVersion"];

  resolve(dictionary);
}

@end

这个类使用 RCTBridgeModule 协议并实现 RCT_EXPORT_MODULERCT_EXPORT_METHOD 宏,它们分别用于指定模块名称和方法名以及暴露给 JavaScript 端。

  1. AppDelegate.m 中注册 Native 模块:
#import "DeviceInfoModule.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  [self addCustomModuleToBridge:bridge];

  rootView = [[RCTRootView alloc] initWithBridge:bridge
                                       moduleName:@"App"
                                initialProperties:nil];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];

  return YES;
}

- (void)addCustomModuleToBridge:(RCTBridge *)bridge {
  [bridge registerModule:[[DeviceInfoModule alloc] init]];
}

在这里,我们创建了一个 RCTBridge 对象并在其中注册了刚刚创建的 Native 模块。

  1. 在 JavaScript 端调用 Native 模块:
import { NativeModules } from 'react-native';

const { DeviceInfo } = NativeModules;

DeviceInfo.getDeviceInfo().then(result => {
  console.log(result); // { name: 'xx', systemName: 'iOS', systemVersion: 'x.x.x' }
}).catch(error => {
  console.log(error);
});

在 JavaScript 中,我们和 Android 一样,使用 NativeModules 对象来获取刚刚创建的 Native 模块,并且使用 getDeviceInfo() 方法来获取设备信息。

总结

本文详细介绍了 React Native 模块 Native 模块封装的步骤,并且提供了 Android 和 iOS 两种平台的示例代码。通过封装 Native 模块,我们可以方便地扩展 React Native 的使用能力,提高开发效率。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a90181add4f0e0ff24ae4f


纠错反馈