Android 生命周期监听器
编辑
了解机制,使您的库能够通过 Expo 模块 API 挂钩 Android Activity 和 Application 功能。
为了响应与应用相关的某些 Android 系统事件,例如传入链接和配置更改,必须覆盖 MainActivity.java 和/或 MainApplication.java 中相应的生命周期回调。
React Native 模块 API 没有提供任何机制来挂钩这些事件,因此 React Native 库的设置说明通常包括将代码复制到这些文件的步骤。为了简化和自动化设置和维护,Expo Modules API 提供了一种机制,允许您的库挂钩 Activity 或 Application 函数。
开始使用
首先,您需要创建一个 Expo 模块或使用 React Native 模块 API 集成 Expo 模块 API。 了解更多。
在您的模块中,创建一个实现 Package 接口的具体类。在大多数情况下,您只需要实现 createReactActivityLifecycleListeners 或 createApplicationLifecycleListeners 方法。
Activity 生命周期监听器
您可以使用 ReactActivityLifecycleListener 挂钩 Activity 生命周期。ReactActivityLifecycleListener 使用其 ReactActivityDelegate 挂钩 React Native 的 ReactActivity 生命周期,并提供与 Android Activity 生命周期类似的体验。
当前支持以下 Activity 生命周期回调:
onCreateonResumeonPauseonDestroyonNewIntentonBackPressed
要创建 ReactActivityLifecycleListener,您应该在派生的 Package 类中实现 createReactActivityLifecycleListeners。例如,MyLibPackage。
// android/src/main/java/expo/modules/mylib/MyLibPackage.kt package expo.modules.mylib import android.content.Context import expo.modules.core.interfaces.Package import expo.modules.core.interfaces.ReactActivityLifecycleListener class MyLibPackage : Package { override fun createReactActivityLifecycleListeners(activityContext: Context): List<ReactActivityLifecycleListener> { return listOf(MyLibReactActivityLifecycleListener()) } }
// android/src/main/java/expo/modules/mylib/MyLibPackage.java package expo.modules.mylib; import android.content.Context; import expo.modules.core.interfaces.Package; import expo.modules.core.interfaces.ReactActivityLifecycleListener; import java.util.Collections; import java.util.List; public class MyLibPackage implements Package { @Override public List<? extends ReactActivityLifecycleListener> createReactActivityLifecycleListeners(Context activityContext) { return Collections.singletonList(new MyLibReactActivityLifecycleListener()); } }
MyLibReactActivityLifecycleListener 是一个派生自 ReactActivityLifecycleListener 的类,您可以在其中挂钩生命周期。您只需重写所需的方法。
// android/src/main/java/expo/modules/mylib/MyLibReactActivityLifecycleListener.kt package expo.modules.mylib import android.app.Activity import android.os.Bundle import expo.modules.core.interfaces.ReactActivityLifecycleListener class MyLibReactActivityLifecycleListener : ReactActivityLifecycleListener { override fun onCreate(activity: Activity, savedInstanceState: Bundle?) { // 在 `Activity.onCreate` 中执行您的初始化代码。 doSomeSetupInActivityOnCreate(activity) } }
// android/src/main/java/expo/modules/mylib/MyLibReactActivityLifecycleListener.java package expo.modules.mylib; import android.app.Activity; import android.os.Bundle; import expo.modules.core.interfaces.ReactActivityLifecycleListener; public class MyLibReactActivityLifecycleListener implements ReactActivityLifecycleListener { @Override public void onCreate(Activity activity, Bundle savedInstanceState) { // 在 `Activity.onCreate` 中执行您的初始化代码。 doSomeSetupInActivityOnCreate(activity); } }
您还可以重写其他生命周期方法。以下示例显示了如何在单个监听器类中重写多个生命周期方法。该示例基于 expo-linking 模块,它使用不同的生命周期方法来处理深链接。您可以只实现适合您用例的方法:
// android/src/main/java/expo/modules/mylib/MyLibReactActivityLifecycleListener.kt package expo.modules.mylib import android.app.Activity import android.content.Intent import android.os.Bundle import expo.modules.core.interfaces.ReactActivityLifecycleListener class MyLibReactActivityLifecycleListener : ReactActivityLifecycleListener { override fun onCreate(activity: Activity?, savedInstanceState: Bundle?) { // 当活动首次创建时调用 // 在这里初始化您的设置,例如处理深链接 val deepLinkUrl = activity?.intent?.data if (deepLinkUrl != null) { handleDeepLink(deepLinkUrl.toString()) } } override fun onResume(activity: Activity) { // 当活动进入前台时调用 // 例如,跟踪用户何时返回到应用程序 trackAppStateChange("active") } override fun onPause(activity: Activity) { // 当活动进入后台时调用 // 例如,暂停正在进行的操作,例如跟踪分析 trackAppStateChange("inactive") } override fun onDestroy(activity: Activity) { // 当活动被销毁时调用 // 在这里清理资源 cleanup() } override fun onNewIntent(intent: Intent?): Boolean { // 当应用程序在运行时接收到新的意图时调用 // 例如,在应用程序打开时处理新的深链接 val newUrl = intent?.data if (newUrl != null) { handleDeepLink(newUrl.toString()) return true } return false } override fun onBackPressed(): Boolean { // 当用户按下返回按钮时调用 // 返回 true 以防止默认的返回行为 return handleCustomBackNavigation() } // 现在,您可以添加私有函数来处理 // 您的深链接、应用状态跟踪、清理等逻辑。 }
// android/src/main/java/expo/modules/mylib/MyLibReactActivityLifecycleListener.java package expo.modules.mylib; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import expo.modules.core.interfaces.ReactActivityLifecycleListener; public class MyLibReactActivityLifecycleListener implements ReactActivityLifecycleListener { @Override public void onCreate(Activity activity, Bundle savedInstanceState) { // 当活动首次创建时调用 // 在这里初始化您的设置,例如处理深链接 Uri deepLinkUrl = activity.getIntent().getData(); if (deepLinkUrl != null) { handleDeepLink(deepLinkUrl.toString()); } } @Override public void onResume(Activity activity) { // 当活动进入前台时调用 // 例如,跟踪用户何时返回到应用程序 trackAppStateChange("active"); } @Override public void onPause(Activity activity) { // 当活动进入后台时调用 // 例如,暂停正在进行的操作,例如跟踪分析 trackAppStateChange("inactive"); } @Override public void onDestroy(Activity activity) { // 当活动被销毁时调用 // 在这里清理资源 cleanup(); } @Override public boolean onNewIntent(Intent intent) { // 当应用程序在运行时接收到新的意图时调用 // 例如,在应用程序打开时处理新的深链接 Uri newUrl = intent.getData(); if (newUrl != null) { handleDeepLink(newUrl.toString()); return true; } return false; } @Override public boolean onBackPressed() { // 当用户按下返回按钮时调用 // 返回 true 以防止默认的返回行为 return handleCustomBackNavigation(); } // 现在,您可以添加私有函数来处理 // 您的深链接、应用状态跟踪、清理等逻辑。 }
JavaScript 事件流的生命周期监听器
生命周期监听器是独立于您的 Expo 模块实例的单例类。要在生命周期监听器和您的模块之间进行通信(例如,将事件发送到应用程序的 JavaScript 代码),您需要观察来自模块的事件,并在事件发生时通知生命周期监听器。典型的流程可能包括以下步骤:
- 系统集成:生命周期监听器捕获带有 URL 数据的 Android 意图
- 观察者模式:单例生命周期监听器与模块实例通信
- 事件桥接:模块将结构化事件发送到 JavaScript
- 内存管理:弱引用防止内存泄漏
- 类型安全和 React 集成:通过适当的事件类型和自定义钩子提供 TypeScript 支持,便于访问深链接事件
您的自定义模块实现可能不需要上述所有内容。不过,您可以将此模式调整为其他系统事件,例如应用状态更改、配置更改或需要将 Android 生命周期事件桥接到 React Native 应用程序的自定义业务逻辑。
以下示例演示如何使用生命周期监听器将 Android 系统事件桥接到您的 React Native 应用程序。该示例基于 expo-linking,该模块使用生命周期监听器创建一个深链接处理程序,当应用程序打开或接收新意图时捕获 URL。
1
模块注册
首先创建一个模块类,注册您的生命周期监听器:
// android/src/main/java/expo/modules/deeplinkhandler/DeepLinkHandlerPackage.kt package expo.modules.deeplinkhandler import android.content.Context import expo.modules.core.interfaces.Package import expo.modules.core.interfaces.ReactActivityLifecycleListener class DeepLinkHandlerPackage : Package { override fun createReactActivityLifecycleListeners(activityContext: Context?): List<ReactActivityLifecycleListener> { return listOf(DeepLinkHandlerActivityLifecycleListener()) } }
// android/src/main/java/expo/modules/deeplinkhandler/DeepLinkHandlerPackage.java package expo.modules.deeplinkhandler; import android.content.Context; import expo.modules.core.interfaces.Package; import expo.modules.core.interfaces.ReactActivityLifecycleListener; import java.util.Collections; import java.util.List; public class DeepLinkHandlerPackage implements Package { @Override public List<? extends ReactActivityLifecycleListener> createReactActivityLifecycleListeners(Context activityContext) { return Collections.singletonList(new DeepLinkHandlerActivityLifecycleListener()); } }
2
带有观察者通知的 Activity 生命周期监听器
创建一个生命周期监听器,捕获深链接并通知模块观察者:
// android/src/main/java/expo/modules/deeplinkhandler/DeepLinkHandlerActivityLifecycleListener.kt package expo.modules.deeplinkhandler import android.app.Activity import android.content.Intent import android.net.Uri import android.os.Bundle import expo.modules.core.interfaces.ReactActivityLifecycleListener class DeepLinkHandlerActivityLifecycleListener : ReactActivityLifecycleListener { override fun onCreate(activity: Activity?, savedInstanceState: Bundle?) { handleIntent(activity?.intent) } override fun onNewIntent(intent: Intent?): Boolean { handleIntent(intent) return true } private fun handleIntent(intent: Intent?) { val url = intent?.data if (url != null) { // 存储初始 URL,以便以后检索 DeepLinkHandlerModule.initialUrl = url // 通知所有观察者新的深链接 DeepLinkHandlerModule.urlReceivedObservers.forEach { observer -> observer(url) } } } }
// android/src/main/java/expo/modules/deeplinkhandler/DeepLinkHandlerActivityLifecycleListener.java package expo.modules.deeplinkhandler; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import expo.modules.core.interfaces.ReactActivityLifecycleListener; public class DeepLinkHandlerActivityLifecycleListener implements ReactActivityLifecycleListener { @Override public void onCreate(Activity activity, Bundle savedInstanceState) { handleIntent(activity.getIntent()); } @Override public boolean onNewIntent(Intent intent) { handleIntent(intent); return true; } private void handleIntent(Intent intent) { if (intent == null) return; Uri url = intent.getData(); if (url != null) { // 存储初始 URL,以便以后检索 DeepLinkHandlerModule.initialUrl = url; // 通知所有观察者新的深链接 for (java.util.function.Consumer<Uri> observer : DeepLinkHandlerModule.urlReceivedObservers) { observer.accept(url); } } } }
3
具有事件发送的 Expo 模块
创建一个模块,维护观察者并将事件发送给 JavaScript:
// android/src/main/java/expo/modules/deeplinkhandler/DeepLinkHandlerModule.kt package expo.modules.deeplinkhandler import android.net.Uri import androidx.core.os.bundleOf import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition import java.lang.ref.WeakReference class DeepLinkHandlerModule : Module() { companion object { var initialUrl: Uri? = null var urlReceivedObservers: MutableSet<((Uri) -> Unit)> = mutableSetOf() } private var urlReceivedObserver: ((Uri) -> Unit)? = null override fun definition() = ModuleDefinition { Name("DeepLinkHandler") Events("onUrlReceived") Function("getInitialUrl") { initialUrl?.toString() } OnStartObserving("onUrlReceived") { val weakModule = WeakReference(this@DeepLinkHandlerModule) val observer: (Uri) -> Unit = { uri -> weakModule.get()?.sendEvent( "onUrlReceived", bundleOf( "url" to uri.toString(), "scheme" to uri.scheme, "host" to uri.host, "path" to uri.path ) ) } urlReceivedObservers.add(observer) urlReceivedObserver = observer } OnStopObserving("onUrlReceived") { urlReceivedObservers.remove(urlReceivedObserver) } } }
// android/src/main/java/expo/modules/deeplinkhandler/DeepLinkHandlerModule.java package expo.modules.deeplinkhandler; import android.net.Uri; import androidx.core.os.Bundle; import expo.modules.kotlin.modules.Module; import expo.modules.kotlin.modules.ModuleDefinition; import java.lang.ref.WeakReference; import java.util.HashSet; import java.util.Set; import java.util.function.Consumer; public class DeepLinkHandlerModule extends Module { public static Uri initialUrl = null; public static Set<Consumer<Uri>> urlReceivedObservers = new HashSet<>(); private Consumer<Uri> urlReceivedObserver; @Override public ModuleDefinition definition() { return ModuleDefinition.create() .name("DeepLinkHandler") .events("onUrlReceived") .function("getInitialUrl", () -> { return initialUrl != null ? initialUrl.toString() : null; }) .onStartObserving("onUrlReceived", () -> { WeakReference<DeepLinkHandlerModule> weakModule = new WeakReference<>(this); Consumer<Uri> observer = uri -> { DeepLinkHandlerModule module = weakModule.get(); if (module != null) { Bundle bundle = new Bundle(); bundle.putString("url", uri.toString()); bundle.putString("scheme", uri.getScheme()); bundle.putString("host", uri.getHost()); bundle.putString("path", uri.getPath()); module.sendEvent("onUrlReceived", bundle); } }; urlReceivedObservers.add(observer); urlReceivedObserver = observer; }) .onStopObserving("onUrlReceived", () -> { urlReceivedObservers.remove(urlReceivedObserver); }); } }
4
TypeScript 接口和 React 使用
为您的模块定义一个 TypeScript 接口,以桥接 Android 生命周期事件到 JavaScript:
import { requireNativeModule, NativeModule } from 'expo-modules-core'; export type DeepLinkEvent = { url: string; scheme?: string; host?: string; path?: string; }; type DeepLinkHandlerModuleEvents = { onUrlReceived(event: DeepLinkEvent): void; }; declare class DeepLinkHandlerNativeModule extends NativeModule<DeepLinkHandlerModuleEvents> { getInitialUrl(): string | null; } const DeepLinkHandler = requireNativeModule<DeepLinkHandlerNativeModule>('DeepLinkHandler'); export default DeepLinkHandler;
为深链接事件提供易于访问的 React 钩子:
import { useEffect, useState } from 'react'; import DeepLinkHandler, { DeepLinkEvent } from './DeepLinkHandler'; export function useDeepLinkHandler(): { initialUrl: string | null; url: string | null; event: DeepLinkEvent | null; } { const [initialUrl] = useState<string | null>(DeepLinkHandler.getInitialUrl()); const [event, setEvent] = useState<DeepLinkEvent | null>(null); useEffect(() => { const subscription = DeepLinkHandler.addListener('onUrlReceived', event => { setEvent(event); }); return () => subscription.remove(); }, []); return { initialUrl, url: event?.url ?? initialUrl, event, }; }
在您的 React 组件中使用它:
import { Text, View, StyleSheet } from 'react-native'; import { useDeepLinkHandler } from './useDeepLinkHandler'; export function App() { const { initialUrl, url, event } = useDeepLinkHandler(); return ( <View style={styles.container}> <Text>Initial URL: {initialUrl || 'None'}</Text> <Text>Current URL: {url || 'None'}</Text> {event && ( <View style={styles.textContainer}> <Text>Latest Deep Link:</Text> <Text>Scheme: {event.scheme}</Text> <Text>Host: {event.host}</Text> <Text>Path: {event.path}</Text> </View> )} </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, textContainer: { marginTop: 20, }, });
5
Application 生命周期监听器
您可以使用 ApplicationLifecycleListener 挂钩 Application 生命周期。
当前支持以下 Application 生命周期回调:
onCreateonConfigurationChanged
要创建 ApplicationLifecycleListener,您应该在派生的 Package 类中实现 createApplicationLifecycleListeners。例如,MyLibPackage。
// android/src/main/java/expo/modules/mylib/MyLibPackage.kt package expo.modules.mylib import android.content.Context import expo.modules.core.interfaces.ApplicationLifecycleListener import expo.modules.core.interfaces.Package class MyLibPackage : Package { override fun createApplicationLifecycleListeners(context: Context): List<ApplicationLifecycleListener> { return listOf(MyLibApplicationLifecycleListener()) } }
// android/src/main/java/expo/modules/mylib/MyLibPackage.java import android.content.Context; import java.util.Collections; import java.util.List; import expo.modules.core.interfaces.ApplicationLifecycleListener; import expo.modules.core.interfaces.Package; public class MyLibPackage implements Package { @Override public List<? extends ApplicationLifecycleListener> createApplicationLifecycleListeners(Context context) { return Collections.singletonList(new MyLibApplicationLifecycleListener()); } }
MyLibApplicationLifecycleListener 是一个派生自 ApplicationLifecycleListener 的类,可以挂钩 Application 生命周期回调。您仅应重写所需的方法(由于可能的维护成本)。
// android/src/main/java/expo/modules/mylib/MyLibApplicationLifecycleListener.kt package expo.modules.mylib import android.app.Application import expo.modules.core.interfaces.ApplicationLifecycleListener class MyLibApplicationLifecycleListener : ApplicationLifecycleListener { override fun onCreate(application: Application) { // 在 `Application.onCreate` 中执行您的初始化代码。 doSomeSetupInApplicationOnCreate(application) } }
// android/src/main/java/expo/modules/mylib/MyLibApplicationLifecycleListener.java package expo.modules.mylib; import android.app.Application; import expo.modules.core.interfaces.ApplicationLifecycleListener; public class MyLibApplicationLifecycleListener implements ApplicationLifecycleListener { @Override public void onCreate(Application application) { // 在 `Application.onCreate` 中执行您的初始化代码。 doSomeSetupInApplicationOnCreate(application); } }
已知问题
为什么没有 onStart 和 onStop Activity 监听器
在当前实现中,我们没有从 MainActivity 设置钩子,而是从 ReactActivityDelegate 设置。MainActivity 和 ReactActivityDelegate 之间存在一些细微的差异。由于 ReactActivityDelegate 没有 onStart 和 onStop,我们在这里尚不支持它们。
接口稳定性
监听器接口可能会在 Expo SDK 发布之间发生变化。我们的向后兼容性策略始终是添加新的接口,并对我们计划删除的接口添加 @Deprecated 注释。我们的接口均基于 Java 8 接口默认方法;您不必也不应实现所有方法。这样做将有利于在不同的 Expo SDK 之间降低模块的维护成本。