From 20a0f224ba133e56f8745eb4e813d81bbc7d5936 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 1 Nov 2019 09:35:40 -0700 Subject: [PATCH] Fabric: Introducing `RCTMountingTransactionObserving` protocol Summary: See the comment in RCTMountingTransactionObserving first. I think we have to add this to the iOS mounting layer to be able reasonably easy implement things like: * MovableNavigationBar: seems, currently we don't handle the situation when the container was mounted first and the nested scroll view second. * TTI component: It does not have access to telemetry. The protocol is meant to replace `RCTSurfacePresenterObserver`. Changelog: [Internal] Fabric-specific change. Reviewed By: mdvacca Differential Revision: D16270107 fbshipit-source-id: 2d4bdb7d0092cc214cc433fc633e41e58f6677df --- .../RCTMountingTransactionObserving.h | 64 +++++++++++++++++++ .../mounting/MountingTransactionMetadata.cpp | 12 ++++ .../mounting/MountingTransactionMetadata.h | 31 +++++++++ 3 files changed, 107 insertions(+) create mode 100644 React/Fabric/Mounting/RCTMountingTransactionObserving.h create mode 100644 ReactCommon/fabric/mounting/MountingTransactionMetadata.cpp create mode 100644 ReactCommon/fabric/mounting/MountingTransactionMetadata.h diff --git a/React/Fabric/Mounting/RCTMountingTransactionObserving.h b/React/Fabric/Mounting/RCTMountingTransactionObserving.h new file mode 100644 index 00000000000..79780dd3355 --- /dev/null +++ b/React/Fabric/Mounting/RCTMountingTransactionObserving.h @@ -0,0 +1,64 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/* + * # Achtung! + * Remember, with great power comes great responsibility. + * Observers of this protocol are being called several times on every single mount transaction. Any thoughtless or + * suboptimal implementation of this protocol will slow down the whole app. Please, be responsible. + * + * # Usecases + * React Native platform-specific mounting layer has limitations when it comes to notifying view components about + * (coming or just happened) changes in the view tree. Implementing that generically for all components would make + * everything way to slow. For instance, the mounting layer does not have dedicated APIs to notify some component that: + * - Some ancestor of the component was reparented; + * - Some descendant of the component was added, removed or reparented; + * - Some ancestor of the component got new layout metrics (which might affect the absolute position of the component); + * - The transaction which affected the component's children just finished. + * + * If some very specific component (e.g. a performance logger) needs to handle some of the similar use-cases, it might + * rely on this protocol. + * + * # How to use + * - Declare conformance to this protocol for the ComponentView class. + * - Implement methods *only* suitable for a particular use case. Do not implement all methods if it is not strictly + * required. + * - Alternatively, an observer can be registered explicitly via `RCTSurface`. + * + * # Implementation details + * The framework checks all registered view classes for conformance to the protocol and for a set of implemented + * methods, then it stores this information for future use. When a view got created, the framework checks the info + * associated with the class and adds the view object to the list of listeners of the particular events (if needed). + * When a view got destroyed, the framework removes the view from suitable collections. + */ +@protocol RCTMountingTransactionObserving + +@optional + +/* + * Called right before the fist mutation instruction is executed. + * Is not being called for a component view which is being mounted as part of the transaction (because the view is not + * registered as an observer yet). + */ +- (void)mountingTransactionWillMountWithMetadata:(facebook::react::MountingTransactionMetadata const &)metadata; + +/* + * Called right after the last mutation instruction is executed. + * Is not being called for a component view which was being unmounted as part of the transaction (because the view is + * not registered as an observer already). + */ +- (void)mountingTransactionDidMountWithMetadata:(facebook::react::MountingTransactionMetadata const &)metadata; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ReactCommon/fabric/mounting/MountingTransactionMetadata.cpp b/ReactCommon/fabric/mounting/MountingTransactionMetadata.cpp new file mode 100644 index 00000000000..1089b05bd3f --- /dev/null +++ b/ReactCommon/fabric/mounting/MountingTransactionMetadata.cpp @@ -0,0 +1,12 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "MountingTransactionMetadata.h" + +namespace facebook { +namespace react {} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/mounting/MountingTransactionMetadata.h b/ReactCommon/fabric/mounting/MountingTransactionMetadata.h new file mode 100644 index 00000000000..8858deaf00f --- /dev/null +++ b/ReactCommon/fabric/mounting/MountingTransactionMetadata.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include + +namespace facebook { +namespace react { + +/* + * Contains all (meta)information related to a MountingTransaction except a list + * of mutation instructions. + * The class is meant to be used when a cosumer should not have access to all + * information about the transaction (incapsulation) but still needs to observe + * it to produce some side-effects. + */ +class MountingTransactionMetadata final { + public: + SurfaceId surfaceId; + MountingTransaction::Number number; + MountingTelemetry telemetry; +}; + +} // namespace react +} // namespace facebook