跳到主要内容

Android 原生模块

信息

原生模块和原生组件是传统架构使用的稳定技术。当新架构稳定后,它们将在未来被弃用。新架构使用 Turbo 原生模块Fabric 原生组件 来实现类似的结果。

欢迎阅读 Android 原生模块。请先阅读原生模块介绍,了解原生模块是什么。

创建日历原生模块

在下面的指南中,你将创建一个名为 CalendarModule 的原生模块,它将允许你从 JavaScript 访问 Android 的日历 API。最终,你将能够从 JavaScript 调用 CalendarModule.createCalendarEvent('Dinner Party', 'My House');,从而调用一个创建日历事件的 Java/Kotlin 方法。

设置

首先,在 Android Studio 中打开 React Native 应用程序中的 Android 项目。你可以在 React Native 应用程序中找到 Android 项目

Image of opening up an Android project within a React Native app inside of Android Studio.
你可以在哪里找到 Android 项目的图片

我们建议使用 Android Studio 编写原生代码。Android Studio 是一个专为 Android 开发构建的 IDE,使用它可以帮助你快速解决代码语法错误等小问题。

我们还建议启用 Gradle Daemon,以加快迭代 Java/Kotlin 代码时的构建速度。

创建自定义原生模块文件

第一步是在 android/app/src/main/java/com/your-app-name/ 文件夹中创建 (CalendarModule.javaCalendarModule.kt) Java/Kotlin 文件(Kotlin 和 Java 的文件夹相同)。此 Java/Kotlin 文件将包含你的原生模块 Java/Kotlin 类。

Image of adding a class called CalendarModule.java within the Android Studio.
如何添加 CalendarModuleClass 的图片

然后添加以下内容

java
package com.your-apps-package-name; // replace your-apps-package-name with your app’s package name
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.util.Map;
import java.util.HashMap;

public class CalendarModule extends ReactContextBaseJavaModule {
CalendarModule(ReactApplicationContext context) {
super(context);
}
}

如你所见,你的 CalendarModule 类扩展了 ReactContextBaseJavaModule 类。对于 Android,Java/Kotlin 原生模块被编写为扩展 ReactContextBaseJavaModule 并实现 JavaScript 所需功能的类。

注意

值得注意的是,从技术上讲,Java/Kotlin 类只需要扩展 BaseJavaModule 类或实现 NativeModule 接口即可被 React Native 视为原生模块。

然而,我们建议你使用 ReactContextBaseJavaModule,如上所示。ReactContextBaseJavaModule 提供了对 ReactApplicationContext (RAC) 的访问,这对于需要挂接到 Activity 生命周期方法的原生模块非常有用。使用 ReactContextBaseJavaModule 也将使你的原生模块在未来更容易实现类型安全。对于原生模块类型安全(将在未来的版本中推出),React Native 会查看每个原生模块的 JavaScript 规范并生成一个扩展 ReactContextBaseJavaModule 的抽象基类。

模块名称

Android 中的所有 Java/Kotlin 原生模块都需要实现 getName() 方法。此方法返回一个字符串,表示原生模块的名称。然后可以使用其名称在 JavaScript 中访问原生模块。例如,在下面的代码片段中,getName() 返回 "CalendarModule"

java
// add to CalendarModule.java
@Override
public String getName() {
return "CalendarModule";
}

然后可以在 JS 中像这样访问原生模块

tsx
const {CalendarModule} = ReactNative.NativeModules;

将原生方法导出到 JavaScript

接下来,你需要向原生模块添加一个方法,该方法将创建日历事件并可在 JavaScript 中调用。所有旨在从 JavaScript 调用的原生模块方法都必须使用 @ReactMethod 进行注解。

CalendarModule 设置一个 createCalendarEvent() 方法,该方法可以通过 CalendarModule.createCalendarEvent() 在 JS 中调用。目前,该方法将接受名称和位置作为字符串。参数类型选项将在稍后介绍。

java
@ReactMethod
public void createCalendarEvent(String name, String location) {
}

在该方法中添加一个调试日志,以确认当你从应用程序中调用它时它已被调用。下面是一个如何从 Android util 包导入和使用 Log 类的示例

java
import android.util.Log;

@ReactMethod
public void createCalendarEvent(String name, String location) {
Log.d("CalendarModule", "Create event called with name: " + name
+ " and location: " + location);
}

完成原生模块的实现并将其连接到 JavaScript 后,你可以按照这些步骤查看应用程序的日志。

同步方法

你可以将 isBlockingSynchronousMethod = true 传递给原生方法,将其标记为同步方法。

java
@ReactMethod(isBlockingSynchronousMethod = true)

目前,我们不建议这样做,因为同步调用方法可能会对性能造成严重影响,并给你的原生模块带来与线程相关的错误。此外,请注意,如果你选择启用 isBlockingSynchronousMethod,你的应用程序将无法再使用 Google Chrome 调试器。这是因为同步方法要求 JS VM 与应用程序共享内存。对于 Google Chrome 调试器,React Native 在 Google Chrome 的 JS VM 中运行,并通过 WebSockets 与移动设备异步通信。

注册模块(Android 特定)

原生模块编写完成后,需要向 React Native 注册。为此,你需要将原生模块添加到 ReactPackage 中,并将 ReactPackage 注册到 React Native。在初始化期间,React Native 将遍历所有包,并为每个 ReactPackage 注册其中的每个原生模块。

React Native 调用 ReactPackage 上的 createNativeModules() 方法以获取要注册的原生模块列表。对于 Android,如果模块未在 createNativeModules 中实例化并返回,则它将无法从 JavaScript 获得。

要将你的原生模块添加到 ReactPackage,首先在 android/app/src/main/java/com/your-app-name/ 文件夹中创建一个新的 Java/Kotlin 类(MyAppPackage.javaMyAppPackage.kt),该类实现 ReactPackage

然后添加以下内容

java
package com.your-app-name; // replace your-app-name with your app’s name
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MyAppPackage implements ReactPackage {

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

@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();

modules.add(new CalendarModule(reactContext));

return modules;
}

}

此文件导入你创建的原生模块 CalendarModule。然后它在 createNativeModules() 函数中实例化 CalendarModule 并将其作为 NativeModules 列表返回以进行注册。如果你以后添加更多原生模块,你也可以实例化它们并将它们添加到此处返回的列表中。

注意

值得注意的是,这种注册原生模块的方式会在应用程序启动时急切地初始化所有原生模块,这会增加应用程序的启动时间。你可以使用 TurboReactPackage 作为替代方案。TurboReactPackage 不像 createNativeModules 那样返回实例化原生模块对象的列表,而是实现了一个 getModule(String name, ReactApplicationContext rac) 方法,该方法在需要时创建原生模块对象。TurboReactPackage 目前实现起来有点复杂。除了实现 getModule() 方法,你还必须实现 getReactModuleInfoProvider() 方法,该方法返回包可以实例化的所有原生模块的列表以及实例化它们的函数,例如此处。同样,使用 TurboReactPackage 将使你的应用程序启动时间更快,但目前编写起来有点麻烦。因此,如果你选择使用 TurboReactPackage,请谨慎操作。

要注册 CalendarModule 包,你必须将 MyAppPackage 添加到 ReactNativeHost 的 getPackages() 方法中返回的包列表中。打开你的 MainApplication.javaMainApplication.kt 文件,该文件可以在以下路径中找到:android/app/src/main/java/com/your-app-name/

找到 ReactNativeHost 的 getPackages() 方法,并将你的包添加到 getPackages() 返回的包列表中

java
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
packages.add(new MyAppPackage());
return packages;
}

你现在已经成功为 Android 注册了原生模块!

测试你构建的内容

至此,你已为 Android 中的原生模块设置了基本骨架。通过访问原生模块并在 JavaScript 中调用其导出的方法来测试它。

在你的应用程序中找到一个你想要添加调用原生模块 createCalendarEvent() 方法的位置。下面是一个组件 NewModuleButton 的示例,你可以将其添加到你的应用程序中。你可以在 NewModuleButtononPress() 函数中调用原生模块。

tsx
import React from 'react';
import {NativeModules, Button} from 'react-native';

const NewModuleButton = () => {
const onPress = () => {
console.log('We will invoke the native module here!');
};

return (
<Button
title="Click to invoke your native module!"
color="#841584"
onPress={onPress}
/>
);
};

export default NewModuleButton;

为了从 JavaScript 访问你的原生模块,你需要首先从 React Native 导入 NativeModules

tsx
import {NativeModules} from 'react-native';

然后你可以从 NativeModules 中访问 CalendarModule 原生模块。

tsx
const {CalendarModule} = NativeModules;

现在你有了 CalendarModule 原生模块,你可以调用你的原生方法 createCalendarEvent()。下面它被添加到 NewModuleButtononPress() 方法中

tsx
const onPress = () => {
CalendarModule.createCalendarEvent('testName', 'testLocation');
};

最后一步是重新构建 React Native 应用程序,以便你可以获得最新的原生代码(包含你的新原生模块!)。在你的命令行中,在 React Native 应用程序所在的位置,运行以下命令

shell
npm run android

迭代构建

当你通读这些指南并迭代你的原生模块时,你需要对你的应用程序进行原生重建,以便从 JavaScript 访问你的最新更改。这是因为你正在编写的代码位于应用程序的原生部分。虽然 React Native 的 metro bundler 可以监视 JavaScript 中的更改并为你即时重建,但它不会对原生代码进行重建。因此,如果你想测试最新的原生更改,你需要使用上述命令进行重建。

回顾✨

你现在应该能够在应用程序中调用你的原生模块上的 createCalendarEvent() 方法。在我们的示例中,这通过按下 NewModuleButton 来实现。你可以通过查看你在 createCalendarEvent() 方法中设置的日志来确认这一点。你可以按照这些步骤查看应用程序中的 ADB 日志。然后你应该能够搜索你的 Log.d 消息(在我们的示例中是“Create event called with name: testName and location: testLocation”),并在每次调用原生模块方法时看到你的消息被记录。

Image of logs.
Android Studio 中的 ADB 日志图片

至此,你已经在 React Native 应用程序中创建了一个 Android 原生模块,并从 JavaScript 调用了它的原生方法。你可以继续阅读以了解有关原生模块方法可用的参数类型以及如何设置回调和 Promise 等更多信息。

超越日历原生模块

更好的原生模块导出

像上面那样通过从 NativeModules 中拉取原生模块来导入有点笨拙。

为了避免你的原生模块的消费者每次想要访问你的原生模块时都需要这样做,你可以为模块创建一个 JavaScript 包装器。创建一个名为 CalendarModule.js 的新 JavaScript 文件,内容如下

tsx
/**
* This exposes the native CalendarModule module as a JS module. This has a
* function 'createCalendarEvent' which takes the following parameters:

* 1. String name: A string representing the name of the event
* 2. String location: A string representing the location of the event
*/
import {NativeModules} from 'react-native';
const {CalendarModule} = NativeModules;
export default CalendarModule;

此 JavaScript 文件也成为你添加任何 JavaScript 端功能的好地方。例如,如果你使用 TypeScript 等类型系统,你可以在此处为你的原生模块添加类型注解。虽然 React Native 尚不支持原生到 JS 的类型安全,但你的所有 JS 代码都将是类型安全的。这样做也将使你更容易在以后切换到类型安全的原生模块。下面是为 CalendarModule 添加类型安全的示例

tsx
/**
* This exposes the native CalendarModule module as a JS module. This has a
* function 'createCalendarEvent' which takes the following parameters:
*
* 1. String name: A string representing the name of the event
* 2. String location: A string representing the location of the event
*/
import {NativeModules} from 'react-native';
const {CalendarModule} = NativeModules;
interface CalendarInterface {
createCalendarEvent(name: string, location: string): void;
}
export default CalendarModule as CalendarInterface;

在你的其他 JavaScript 文件中,你可以像这样访问原生模块并调用其方法

tsx
import CalendarModule from './CalendarModule';
CalendarModule.createCalendarEvent('foo', 'bar');
注意

这假设你导入 CalendarModule 的位置与 CalendarModule.js 处于相同的层级。请根据需要更新相对导入。

参数类型

当在 JavaScript 中调用原生模块方法时,React Native 会将参数从 JS 对象转换为其 Java/Kotlin 对象对应物。因此,例如,如果你的 Java 原生模块方法接受一个 double,在 JS 中你需要用一个数字调用该方法。React Native 将为你处理转换。下面列出了原生模块方法支持的参数类型以及它们映射到的 JavaScript 等效项。

JavaKotlinJavaScript
BooleanBoolean?boolean
布尔值布尔值
DoubleDouble?number
double数字
StringString字符串
CallbackCallbackFunction
PromisePromisePromise
ReadableMapReadableMapObject
ReadableArrayReadableArrayArray
信息

目前支持以下类型,但 TurboModules 将不再支持。请避免使用它们

  • Integer Java/Kotlin -> ?number
  • Float Java/Kotlin -> ?number
  • int Java -> number
  • float Java -> number

对于上面未列出的参数类型,你需要自己处理转换。例如,在 Android 中,Date 转换不是开箱即用的。你可以像这样在原生方法中自行处理到 Date 类型的转换

java
    String dateFormat = "yyyy-MM-dd";
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
Calendar eStartDate = Calendar.getInstance();
try {
eStartDate.setTime(sdf.parse(startDate));
}

导出常量

原生模块可以通过实现原生方法 getConstants() 来导出常量,该方法在 JS 中可用。下面你将实现 getConstants() 并返回一个包含 DEFAULT_EVENT_NAME 常量的 Map,你可以在 JavaScript 中访问该常量

java
@Override
public Map<String, Object> getConstants() {
final Map<String, Object> constants = new HashMap<>();
constants.put("DEFAULT_EVENT_NAME", "New Event");
return constants;
}

然后可以通过在 JS 中调用原生模块上的 getConstants 来访问常量

tsx
const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
console.log(DEFAULT_EVENT_NAME);

从技术上讲,可以直接从原生模块对象访问 getConstants() 中导出的常量。TurboModules 将不再支持此功能,因此我们鼓励社区切换到上述方法,以避免以后不必要的迁移。

注意

目前常量只在初始化时导出,因此如果你在运行时更改 getConstants 值,它不会影响 JavaScript 环境。这将在 Turbomodules 中改变。使用 Turbomodules,getConstants() 将成为一个常规的原生模块方法,每次调用都会命中原生端。

回调

原生模块还支持一种独特的参数:回调。回调用于将数据从 Java/Kotlin 传递到 JavaScript 以进行异步方法。它们还可以用于从原生端异步执行 JavaScript。

为了创建带有回调的原生模块方法,首先导入 Callback 接口,然后向你的原生模块方法添加一个类型为 Callback 的新参数。回调参数有一些细微差别,很快将通过 TurboModules 解决。首先,你的函数参数中只能有两个回调——一个 successCallback 和一个 failureCallback。此外,原生模块方法调用的最后一个参数(如果是函数)被视为 successCallback,原生模块方法调用的倒数第二个参数(如果是函数)被视为 failureCallback。

java
import com.facebook.react.bridge.Callback;

@ReactMethod
public void createCalendarEvent(String name, String location, Callback callBack) {
}

你可以在你的 Java/Kotlin 方法中调用回调,提供你想要传递给 JavaScript 的任何数据。请注意,你只能从原生代码传递可序列化的数据到 JavaScript。如果你需要传回原生对象,可以使用 WriteableMaps;如果你需要使用集合,可以使用 WritableArrays。同样重要的是要强调回调在原生函数完成之后不会立即调用。下面,在早期调用中创建的事件的 ID 被传递给回调。

java
  @ReactMethod
public void createCalendarEvent(String name, String location, Callback callBack) {
Integer eventId = ...
callBack.invoke(eventId);
}

然后可以使用 JavaScript 访问此方法

tsx
const onPress = () => {
CalendarModule.createCalendarEvent(
'Party',
'My House',
eventId => {
console.log(`Created a new event with id ${eventId}`);
},
);
};

另一个需要注意的重要细节是,原生模块方法只能调用一个回调一次。这意味着你可以调用成功回调或失败回调,但不能同时调用两者,并且每个回调最多只能调用一次。然而,原生模块可以存储回调并在以后调用它。

回调有两种错误处理方法。第一种是遵循 Node 的约定,将传递给回调的第一个参数视为错误对象。

java
  @ReactMethod
public void createCalendarEvent(String name, String location, Callback callBack) {
Integer eventId = ...
callBack.invoke(null, eventId);
}

在 JavaScript 中,你可以检查第一个参数,看是否有错误传递

tsx
const onPress = () => {
CalendarModule.createCalendarEvent(
'testName',
'testLocation',
(error, eventId) => {
if (error) {
console.error(`Error found! ${error}`);
}
console.log(`event id ${eventId} returned`);
},
);
};

另一个选项是使用 onSuccess 和 onFailure 回调

java
@ReactMethod
public void createCalendarEvent(String name, String location, Callback myFailureCallback, Callback mySuccessCallback) {
}

然后在 JavaScript 中,你可以为错误和成功响应添加单独的回调

tsx
const onPress = () => {
CalendarModule.createCalendarEvent(
'testName',
'testLocation',
error => {
console.error(`Error found! ${error}`);
},
eventId => {
console.log(`event id ${eventId} returned`);
},
);
};

Promise

原生模块还可以履行 Promise,这可以简化你的 JavaScript,尤其是在使用 ES2016 的 async/await 语法时。当原生模块 Java/Kotlin 方法的最后一个参数是 Promise 时,其对应的 JS 方法将返回一个 JS Promise 对象。

将上述代码重构为使用 Promise 而不是回调,如下所示

java
import com.facebook.react.bridge.Promise;

@ReactMethod
public void createCalendarEvent(String name, String location, Promise promise) {
try {
Integer eventId = ...
promise.resolve(eventId);
} catch(Exception e) {
promise.reject("Create Event Error", e);
}
}
注意

与回调类似,原生模块方法可以拒绝或解决 Promise(但不能同时进行),并且最多只能执行一次。这意味着你可以调用成功回调或失败回调,但不能同时调用两者,并且每个回调最多只能调用一次。然而,原生模块可以存储回调并在以后调用它。

此方法的 JavaScript 对应部分返回一个 Promise。这意味着你可以在异步函数中使用 await 关键字来调用它并等待其结果

tsx
const onSubmit = async () => {
try {
const eventId = await CalendarModule.createCalendarEvent(
'Party',
'My House',
);
console.log(`Created a new event with id ${eventId}`);
} catch (e) {
console.error(e);
}
};

reject 方法接受以下参数的不同组合

java
String code, String message, WritableMap userInfo, Throwable throwable

有关更多详细信息,你可以在此处找到 Promise.java 接口。如果未提供 userInfo,ReactNative 会将其设置为 null。对于其余参数,React Native 将使用默认值。message 参数提供错误调用堆栈顶部显示的错误 message。下面是 Java/Kotlin 中以下 reject 调用在 JavaScript 中显示的错误消息示例。

Java/Kotlin reject 调用

java
promise.reject("Create Event error", "Error parsing date", e);

Promise 被拒绝时 React Native 应用中的错误消息

Image of error message in React Native app.
错误消息图片

向 JavaScript 发送事件

原生模块可以在不被直接调用的情况下向 JavaScript 发送事件。例如,你可能希望向 JavaScript 发出提醒,告知 Android 日历应用中的日历事件即将发生。最简单的方法是使用 RCTDeviceEventEmitter,可以从 ReactContext 中获取,如下面的代码片段所示。

java
...
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments;
...
private void sendEvent(ReactContext reactContext,
String eventName,
@Nullable WritableMap params) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
}

private int listenerCount = 0;

@ReactMethod
public void addListener(String eventName) {
if (listenerCount == 0) {
// Set up any upstream listeners or background tasks as necessary
}

listenerCount += 1;
}

@ReactMethod
public void removeListeners(Integer count) {
listenerCount -= count;
if (listenerCount == 0) {
// Remove upstream listeners, stop unnecessary background tasks
}
}
...
WritableMap params = Arguments.createMap();
params.putString("eventProperty", "someValue");
...
sendEvent(reactContext, "EventReminder", params);

JavaScript 模块然后可以通过在 NativeEventEmitter 类上使用 addListener 来注册接收事件。

tsx
import {NativeEventEmitter, NativeModules} from 'react-native';
...
useEffect(() => {
const eventEmitter = new NativeEventEmitter(NativeModules.ToastExample);
let eventListener = eventEmitter.addListener('EventReminder', event => {
console.log(event.eventProperty) // "someValue"
});

// Removes the listener once unmounted
return () => {
eventListener.remove();
};
}, []);

从 startActivityForResult 获取活动结果

如果你想从你使用 startActivityForResult 启动的活动中获取结果,你需要监听 onActivityResult。为此,你必须扩展 BaseActivityEventListener 或实现 ActivityEventListener。前者更受欢迎,因为它对 API 更改更具弹性。然后,你需要像这样在模块的构造函数中注册监听器

java
reactContext.addActivityEventListener(mActivityResultListener);

现在你可以通过实现以下方法来监听 onActivityResult

java
@Override
public void onActivityResult(
final Activity activity,
final int requestCode,
final int resultCode,
final Intent intent) {
// Your logic here
}

让我们实现一个基本的图片选择器来演示这一点。图片选择器将向 JavaScript 暴露 pickImage 方法,该方法在调用时将返回图片的路径。

kotlin
public class ImagePickerModule extends ReactContextBaseJavaModule {

private static final int IMAGE_PICKER_REQUEST = 1;
private static final String E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST";
private static final String E_PICKER_CANCELLED = "E_PICKER_CANCELLED";
private static final String E_FAILED_TO_SHOW_PICKER = "E_FAILED_TO_SHOW_PICKER";
private static final String E_NO_IMAGE_DATA_FOUND = "E_NO_IMAGE_DATA_FOUND";

private Promise mPickerPromise;

private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {

@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
if (requestCode == IMAGE_PICKER_REQUEST) {
if (mPickerPromise != null) {
if (resultCode == Activity.RESULT_CANCELED) {
mPickerPromise.reject(E_PICKER_CANCELLED, "Image picker was cancelled");
} else if (resultCode == Activity.RESULT_OK) {
Uri uri = intent.getData();

if (uri == null) {
mPickerPromise.reject(E_NO_IMAGE_DATA_FOUND, "No image data found");
} else {
mPickerPromise.resolve(uri.toString());
}
}

mPickerPromise = null;
}
}
}
};

ImagePickerModule(ReactApplicationContext reactContext) {
super(reactContext);

// Add the listener for `onActivityResult`
reactContext.addActivityEventListener(mActivityEventListener);
}

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

@ReactMethod
public void pickImage(final Promise promise) {
Activity currentActivity = getCurrentActivity();

if (currentActivity == null) {
promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity doesn't exist");
return;
}

// Store the promise to resolve/reject when picker returns data
mPickerPromise = promise;

try {
final Intent galleryIntent = new Intent(Intent.ACTION_PICK);

galleryIntent.setType("image/*");

final Intent chooserIntent = Intent.createChooser(galleryIntent, "Pick an image");

currentActivity.startActivityForResult(chooserIntent, IMAGE_PICKER_REQUEST);
} catch (Exception e) {
mPickerPromise.reject(E_FAILED_TO_SHOW_PICKER, e);
mPickerPromise = null;
}
}
}

监听生命周期事件

监听活动的生命周期事件,例如 onResumeonPause 等,与实现 ActivityEventListener 的方式非常相似。模块必须实现 LifecycleEventListener。然后,你需要像这样在模块的构造函数中注册监听器

java
reactContext.addLifecycleEventListener(this);

现在你可以通过实现以下方法来监听活动的生命周期事件

java
@Override
public void onHostResume() {
// Activity `onResume`
}
@Override
public void onHostPause() {
// Activity `onPause`
}
@Override
public void onHostDestroy() {
// Activity `onDestroy`
}

线程

迄今为止,在 Android 上,所有原生模块异步方法都在一个线程上执行。原生模块不应假设它们是在哪个线程上被调用的,因为当前的分配在未来可能会改变。如果需要进行阻塞调用,则应将繁重的工作分派到内部管理的 worker 线程,并从那里分发任何回调。