From 0dbe206683551b1f027b2c7aebad14512284c237 Mon Sep 17 00:00:00 2001 From: matinzd <24797481+matinzd@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:06:48 +0100 Subject: [PATCH 1/5] Create 0000-enhanced-lifecycle-aware-module-registry.md --- ...nhanced-lifecycle-aware-module-registry.md | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 proposals/0000-enhanced-lifecycle-aware-module-registry.md diff --git a/proposals/0000-enhanced-lifecycle-aware-module-registry.md b/proposals/0000-enhanced-lifecycle-aware-module-registry.md new file mode 100644 index 00000000..b569a46a --- /dev/null +++ b/proposals/0000-enhanced-lifecycle-aware-module-registry.md @@ -0,0 +1,187 @@ +--- +title: Enhanced lifecycle-aware module registry +author: + - Matin Zadeh Dolatabad +date: 2025-01-06 +--- + +# RFC0000: Enhanced lifecycle-aware module registry + +## Summary + +This RFC proposes a framework to enhance the module registry in React Native by introducing a lifecycle-aware system for native modules. The goal is to address the current gap in handling application lifecycle events, akin to Flutter's `FlutterPlugin` and `FlutterApplicationLifeCycleDelegate`. The design enables seamless integration of native modules with application lifecycle events across iOS and Android platforms. There is also Expo Modules Core that handles this, but React Native does not have this by default and it requires Expo to be used in such cases. + +## Motivation + +React Native lacks a comprehensive and standardized approach for native module lifecycle management. Unlike Flutter, where plugins can hook into application lifecycle events via a well-defined protocol, React Native requires developers to implement custom solutions for such behavior. This limitation results in increased boilerplate code, fragmented implementations, and an inconsistent developer experience. + +### Key Challenges Addressed: + +- **Limited Module Registry:** React Native's module registry doesn't natively support lifecycle awareness. On Android, React Native provides a `LifecycleEventListener` that partially addresses this by allowing modules to listen to events like `onHostResume`, `onHostPause`, and `onHostDestroy`. However, there is no support for early lifecycle events such as `onCreate` or `onTerminate`. On iOS, there is no equivalent lifecycle support, leading to significant gaps in managing the full application lifecycle effectively across platforms. +- **Manual Lifecycle Handling:** Developers must manually wire up lifecycle events for each native module. +- **Inconsistency Across Platforms:** There is no unified approach for managing lifecycle events across iOS and Android except `Expo Modules API`. + +## Detailed Design + +The proposed solution introduces a `LifecycleAwareModule` interface and a centralized lifecycle manager for React Native. This framework would: + +1. Allow native modules to register as lifecycle-aware. +2. Notify registered modules of key application lifecycle events. +3. Provide a consistent API across platforms. + +### iOS Implementation + +Define a protocol for lifecycle-aware modules: + +```objc +@protocol RNLifecycleAwareModule +@optional +- (void)applicationDidFinishLaunching:(UIApplication *)application; +- (void)applicationWillResignActive:(UIApplication *)application; +- (void)applicationDidEnterBackground:(UIApplication *)application; +- (void)applicationWillEnterForeground:(UIApplication *)application; +- (void)applicationDidBecomeActive:(UIApplication *)application; +- (void)applicationWillTerminate:(UIApplication *)application; +@end +``` + +Create a `RNLifecycleManager` to manage registered modules: + +```objc +@interface RNLifecycleManager : NSObject ++ (instancetype)sharedInstance; +- (void)registerModule:(id)module; +- (void)notifyModulesWithSelector:(SEL)selector application:(UIApplication *)application; +@end +``` + +Hook into `AppDelegate`: + +```objc +@implementation AppDelegate +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [[RNLifecycleManager sharedInstance] notifyModulesWithSelector:@selector(applicationDidFinishLaunching:) application:application]; + return YES; +} +@end +``` + +### Android Implementation + +Define an interface for lifecycle-aware modules: + +```kotlin +interface RNLifecycleAwareModule { + fun onCreate(application: Application) + fun onResume() + fun onPause() + fun onStop() + fun onDestroy() +} +``` + +Create a `LifecycleManager` to manage registered modules: + +```kotlin +object LifecycleManager { + private val modules = mutableListOf() + + fun registerModule(module: RNLifecycleAwareModule) { + modules.add(module) + } + + fun notify(event: (RNLifecycleAwareModule) -> Unit) { + modules.forEach { event(it) } + } +} +``` + +Hook into `Application`: + +```kotlin +class MainApplication : Application() { + override fun onCreate() { + super.onCreate() + LifecycleManager.notify { it.onCreate(this) } + } + + override fun onTerminate() { + super.onTerminate() + LifecycleManager.notify { it.onDestroy() } + } +} +``` + +### Usage Inside Libraries + +Libraries can leverage the lifecycle-aware module registry to handle lifecycle events seamlessly. For instance: + +#### iOS Example + +```objc +@interface MyModule : NSObject +@end + +@implementation MyModule + +- (void)applicationDidFinishLaunching:(UIApplication *)application { + // Initialize resources +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Save state +} + +@end +``` + +#### Android Example + +```kotlin +class MyModule : RNLifecycleAwareModule { + override fun onCreate(application: Application) { + // Initialize resources + } + + override fun onPause() { + // Save state + } +} +``` + +By implementing the `RNLifecycleAwareModule` interface, library developers can ensure that their modules respond appropriately to lifecycle events without requiring additional setup from the application developers. + +However the design details here are just a demonstration and the actual implementation may vary. This implementation ca be baked into the current interface or a new interface can be introduced. + +## Drawbacks + +- **Backward Compatibility:** Existing modules will need updates to implement the lifecycle-aware interface. +- **Performance Overhead:** Centralized lifecycle management may introduce performance overhead, especially with many registered modules. +- **Potential Conflicts:** Modules that handle lifecycle events internally may conflict with the centralized lifecycle manager. + +## Alternatives + +### Option 1 + +Use third-party libraries for lifecycle management, but this lacks standardization and official support. + +### Option 2 + +Continue with the current approach, leaving lifecycle management to individual frameworks/developers. + +## Adoption Strategy + +- Introduce as an optional feature in a minor React Native release. +- Provide detailed documentation and examples. +- Encourage library authors to adopt the lifecycle-aware interface for their modules. + +## How We Teach This + +- Update official documentation with lifecycle-aware module examples. +- Provide tutorials and migration guides for developers. +- Offer webinars or workshops to explain the new system. + +## Unresolved Questions + +- How to handle potential performance overhead with many registered modules? +- How to ensure compatibility with existing React Native libraries? From 656ee2c19ff68ce0a1b69b6cdea76160c9556bf0 Mon Sep 17 00:00:00 2001 From: matinzd <24797481+matinzd@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:14:51 +0100 Subject: [PATCH 2/5] Update 0000-enhanced-lifecycle-aware-module-registry.md --- proposals/0000-enhanced-lifecycle-aware-module-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-enhanced-lifecycle-aware-module-registry.md b/proposals/0000-enhanced-lifecycle-aware-module-registry.md index b569a46a..8d6a1d50 100644 --- a/proposals/0000-enhanced-lifecycle-aware-module-registry.md +++ b/proposals/0000-enhanced-lifecycle-aware-module-registry.md @@ -9,7 +9,7 @@ date: 2025-01-06 ## Summary -This RFC proposes a framework to enhance the module registry in React Native by introducing a lifecycle-aware system for native modules. The goal is to address the current gap in handling application lifecycle events, akin to Flutter's `FlutterPlugin` and `FlutterApplicationLifeCycleDelegate`. The design enables seamless integration of native modules with application lifecycle events across iOS and Android platforms. There is also Expo Modules Core that handles this, but React Native does not have this by default and it requires Expo to be used in such cases. +This RFC proposes a framework to enhance the module registry in React Native by introducing a lifecycle-aware system for native modules. The goal is to address the current gap in handling application lifecycle events, similar to Flutter's `FlutterApplicationLifeCycleDelegate` on iOS and `Application.ActivityLifecycleCallbacks` on Android. The design enables seamless integration of native modules with application lifecycle events across iOS and Android platforms. There is also Expo Modules Core that handles this, but React Native does not have this by default and it requires Expo to be used in such cases. ## Motivation From 51253229c4862b15360379e6ac7c201ed66ca4a8 Mon Sep 17 00:00:00 2001 From: matinzd <24797481+matinzd@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:32:19 +0100 Subject: [PATCH 3/5] Add examples --- ...-enhanced-lifecycle-aware-module-registry.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/proposals/0000-enhanced-lifecycle-aware-module-registry.md b/proposals/0000-enhanced-lifecycle-aware-module-registry.md index 8d6a1d50..4d590211 100644 --- a/proposals/0000-enhanced-lifecycle-aware-module-registry.md +++ b/proposals/0000-enhanced-lifecycle-aware-module-registry.md @@ -9,7 +9,7 @@ date: 2025-01-06 ## Summary -This RFC proposes a framework to enhance the module registry in React Native by introducing a lifecycle-aware system for native modules. The goal is to address the current gap in handling application lifecycle events, similar to Flutter's `FlutterApplicationLifeCycleDelegate` on iOS and `Application.ActivityLifecycleCallbacks` on Android. The design enables seamless integration of native modules with application lifecycle events across iOS and Android platforms. There is also Expo Modules Core that handles this, but React Native does not have this by default and it requires Expo to be used in such cases. +This RFC proposes a framework to enhance the module registry in React Native by introducing a lifecycle-aware system for native modules. The goal is to address the current gap in handling application lifecycle events, similar to Flutter's `FlutterApplicationLifeCycleDelegate` on iOS and `Application.ActivityLifecycleCallbacks` on Android. The design enables seamless integration of native modules with application lifecycle events across iOS and Android platforms. There is also Expo Modules Core that handles this via `ExpoAppDelegateSubscriber` and `ReactActivityLifecycleListener`, but React Native does not have this by default and it requires Expo to be used in such cases. ## Motivation @@ -21,6 +21,21 @@ React Native lacks a comprehensive and standardized approach for native module l - **Manual Lifecycle Handling:** Developers must manually wire up lifecycle events for each native module. - **Inconsistency Across Platforms:** There is no unified approach for managing lifecycle events across iOS and Android except `Expo Modules API`. +### Potential use cases: + +- One of the most popular libraries that can benefit from this approach is [React Native Firebase](https://github.com/invertase/react-native-firebase). For example, integrating Firebase on iOS requires adding `[FIRApp configure]` to the `didFinishLaunchingWithOptions` method in the `AppDelegate`. This process could be automated by allowing the Firebase module to implement a lifecycle-aware interface: + ```objc + - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [FIRApp configure]; + // Other initialization code... + return YES; + } + ``` + +- Another libraries like [`react-native-health-connect`](https://github.com/matinzd/react-native-health-connect), [`@braze/react-native-sdk`](https://github.com/braze-inc/braze-react-native-sdk) can benefit from this approach without the need for manual setup and the headache of managing issues related to lifecycle events. + +By supporting lifecycle-aware modules, React Native Firebase and similar libraries can eliminate the need for manual native code changes, making integration smoother and more developer-friendly. + ## Detailed Design The proposed solution introduces a `LifecycleAwareModule` interface and a centralized lifecycle manager for React Native. This framework would: From c1e2dc71d99a444734157f4ae53ea1c333395ce8 Mon Sep 17 00:00:00 2001 From: matinzd <24797481+matinzd@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:38:44 +0100 Subject: [PATCH 4/5] update design details disclaimer --- proposals/0000-enhanced-lifecycle-aware-module-registry.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proposals/0000-enhanced-lifecycle-aware-module-registry.md b/proposals/0000-enhanced-lifecycle-aware-module-registry.md index 4d590211..bb3957ce 100644 --- a/proposals/0000-enhanced-lifecycle-aware-module-registry.md +++ b/proposals/0000-enhanced-lifecycle-aware-module-registry.md @@ -164,9 +164,9 @@ class MyModule : RNLifecycleAwareModule { } ``` -By implementing the `RNLifecycleAwareModule` interface, library developers can ensure that their modules respond appropriately to lifecycle events without requiring additional setup from the application developers. +By implementing the `RNLifecycleAwareModule` interface, library developers can ensure that their modules respond appropriately to lifecycle events without requiring additional setup from application developers. This approach streamlines integration, reducing manual coding and improving consistency across projects. -However the design details here are just a demonstration and the actual implementation may vary. This implementation ca be baked into the current interface or a new interface can be introduced. +While the design details here serve as a conceptual demonstration, the actual implementation may differ based on React Native's evolving architecture. For instance, this could either extend the current module registry or involve introducing a new interface entirely, which may cause breaking changes in some scenarios. These considerations would require careful evaluation during the development phase. ## Drawbacks From 9bf4433f5532bab949d7ddb7dcb6ec83e096846d Mon Sep 17 00:00:00 2001 From: matinzd <24797481+matinzd@users.noreply.github.com> Date: Mon, 6 Jan 2025 19:03:11 +0100 Subject: [PATCH 5/5] use mutableSet --- proposals/0000-enhanced-lifecycle-aware-module-registry.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/0000-enhanced-lifecycle-aware-module-registry.md b/proposals/0000-enhanced-lifecycle-aware-module-registry.md index bb3957ce..922a2cd6 100644 --- a/proposals/0000-enhanced-lifecycle-aware-module-registry.md +++ b/proposals/0000-enhanced-lifecycle-aware-module-registry.md @@ -99,7 +99,7 @@ Create a `LifecycleManager` to manage registered modules: ```kotlin object LifecycleManager { - private val modules = mutableListOf() + private val modules = mutableSetOf() fun registerModule(module: RNLifecycleAwareModule) { modules.add(module)