mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-24 04:16:00 +08:00
RCTUIManagerObserverCoordinator: new way to subscribe for granular notifications from UI Manager
Reviewed By: majak Differential Revision: D4868591 fbshipit-source-id: 24a09ffa3e69dec5ce1f0a8715c7e4701d781996
This commit is contained in:
committed by
Facebook Github Bot
parent
2a984326b0
commit
712b1dd20a
@@ -59,24 +59,7 @@ RCT_EXTERN NSString *const RCTUIManagerDidRemoveRootViewNotification;
|
||||
*/
|
||||
RCT_EXTERN NSString *const RCTUIManagerRootViewKey;
|
||||
|
||||
@class RCTUIManager;
|
||||
|
||||
/**
|
||||
* Allows to hook into UIManager internals. This can be used to execute code at
|
||||
* specific points during the view updating process.
|
||||
*/
|
||||
@protocol RCTUIManagerObserver <NSObject>
|
||||
|
||||
/**
|
||||
* Called before flushing UI blocks at the end of a batch. Note that this won't
|
||||
* get called for partial batches when using `unsafeFlushUIChangesBeforeBatchEnds`.
|
||||
* This is called from the UIManager queue. Can be used to add UI operations in that batch.
|
||||
*/
|
||||
- (void)uiManagerWillFlushUIBlocks:(RCTUIManager *)manager;
|
||||
|
||||
@end
|
||||
|
||||
@protocol RCTScrollableProtocol;
|
||||
@class RCTUIManagerObserverCoordinator;
|
||||
|
||||
/**
|
||||
* The RCTUIManager is the module responsible for updating the view hierarchy.
|
||||
@@ -139,17 +122,6 @@ RCT_EXTERN NSString *const RCTUIManagerRootViewKey;
|
||||
*/
|
||||
- (void)prependUIBlock:(RCTViewManagerUIBlock)block;
|
||||
|
||||
/**
|
||||
* Add a UIManagerObserver. See the RCTUIManagerObserver protocol for more info. This
|
||||
* method can be called safely from any queue.
|
||||
*/
|
||||
- (void)addUIManagerObserver:(id<RCTUIManagerObserver>)observer;
|
||||
|
||||
/**
|
||||
* Remove a UIManagerObserver. This method can be called safely from any queue.
|
||||
*/
|
||||
- (void)removeUIManagerObserver:(id<RCTUIManagerObserver>)observer;
|
||||
|
||||
/**
|
||||
* Used by native animated module to bypass the process of updating the values through the shadow
|
||||
* view hierarchy. This method will directly update native views, which means that updates for
|
||||
@@ -192,6 +164,12 @@ RCT_EXTERN NSString *const RCTUIManagerRootViewKey;
|
||||
*/
|
||||
- (void)setNeedsLayout;
|
||||
|
||||
/**
|
||||
* Dedicated object for subscribing for UIManager events.
|
||||
* See `RCTUIManagerObserver` protocol for more details.
|
||||
*/
|
||||
@property (atomic, retain, readonly) RCTUIManagerObserverCoordinator *observerCoordinator;
|
||||
|
||||
@end
|
||||
|
||||
@interface RCTUIManager (Deprecated)
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#import "RCTScrollableProtocol.h"
|
||||
#import "RCTShadowView.h"
|
||||
#import "RCTUtils.h"
|
||||
#import "RCTUIManagerObserverCoordinator.h"
|
||||
#import "RCTView.h"
|
||||
#import "RCTViewManager.h"
|
||||
#import "UIView+React.h"
|
||||
@@ -225,7 +226,6 @@ static UIViewAnimationOptions UIViewAnimationOptionsFromRCTAnimationType(RCTAnim
|
||||
NSDictionary *_componentDataByName;
|
||||
|
||||
NSMutableSet<id<RCTComponent>> *_bridgeTransactionListeners;
|
||||
NSMutableSet<id<RCTUIManagerObserver>> *_uiManagerObservers;
|
||||
}
|
||||
|
||||
@synthesize bridge = _bridge;
|
||||
@@ -306,7 +306,7 @@ RCT_EXPORT_MODULE()
|
||||
_rootViewTags = [NSMutableSet new];
|
||||
|
||||
_bridgeTransactionListeners = [NSMutableSet new];
|
||||
_uiManagerObservers = [NSMutableSet new];
|
||||
_observerCoordinator = [RCTUIManagerObserverCoordinator new];
|
||||
|
||||
_viewsToBeDeleted = [NSMutableSet new];
|
||||
|
||||
@@ -723,20 +723,6 @@ BOOL RCTIsUIManagerQueue()
|
||||
}
|
||||
}
|
||||
|
||||
- (void)addUIManagerObserver:(id<RCTUIManagerObserver>)observer
|
||||
{
|
||||
dispatch_async(RCTGetUIManagerQueue(), ^{
|
||||
[self->_uiManagerObservers addObject:observer];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)removeUIManagerObserver:(id<RCTUIManagerObserver>)observer
|
||||
{
|
||||
dispatch_async(RCTGetUIManagerQueue(), ^{
|
||||
[self->_uiManagerObservers removeObject:observer];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A method to be called from JS, which takes a container ID and then releases
|
||||
* all subviews for that container upon receipt.
|
||||
@@ -1159,10 +1145,19 @@ RCT_EXPORT_METHOD(dispatchViewManagerCommand:(nonnull NSNumber *)reactTag
|
||||
[self addUIBlock:uiBlock];
|
||||
}
|
||||
|
||||
[_observerCoordinator uiManagerWillPerformLayout:self];
|
||||
|
||||
// Perform layout
|
||||
for (NSNumber *reactTag in _rootViewTags) {
|
||||
RCTRootShadowView *rootView = (RCTRootShadowView *)_shadowViewRegistry[reactTag];
|
||||
[self addUIBlock:[self uiBlockWithLayoutUpdateForRootView:rootView]];
|
||||
}
|
||||
|
||||
[_observerCoordinator uiManagerDidPerformLayout:self];
|
||||
|
||||
// Properies propagation
|
||||
for (NSNumber *reactTag in _rootViewTags) {
|
||||
RCTRootShadowView *rootView = (RCTRootShadowView *)_shadowViewRegistry[reactTag];
|
||||
[self _amendPendingUIBlocksWithStylePropagationUpdateForShadowView:rootView];
|
||||
}
|
||||
|
||||
@@ -1175,9 +1170,7 @@ RCT_EXPORT_METHOD(dispatchViewManagerCommand:(nonnull NSNumber *)reactTag
|
||||
}
|
||||
}];
|
||||
|
||||
for (id<RCTUIManagerObserver> observer in _uiManagerObservers) {
|
||||
[observer uiManagerWillFlushUIBlocks:self];
|
||||
}
|
||||
[_observerCoordinator uiManagerWillFlushUIBlocks:self];
|
||||
|
||||
[self flushUIBlocks];
|
||||
}
|
||||
|
||||
67
React/Modules/RCTUIManagerObserverCoordinator.h
Normal file
67
React/Modules/RCTUIManagerObserverCoordinator.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTViewManager.h>
|
||||
|
||||
/**
|
||||
* Allows to hook into UIManager internals. This can be used to execute code at
|
||||
* specific points during the view updating process.
|
||||
* All observer handler is called on UIManager queue.
|
||||
*/
|
||||
@protocol RCTUIManagerObserver <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
* Called just before the UIManager layout views.
|
||||
* It allows performing some operation for components which contain custom
|
||||
* layout logic right before regular Yoga based layout. So, for instance,
|
||||
* some components which have own React-independent state can compute and cache
|
||||
* own intrinsic content size (which will be used by Yoga) at this point.
|
||||
*/
|
||||
- (void)uiManagerWillPerformLayout:(RCTUIManager *)manager;
|
||||
|
||||
/**
|
||||
* Called just after the UIManager layout views.
|
||||
* It allows performing custom layout logic right after regular Yoga based layout.
|
||||
* So, for instance, this can be used for computing final layout for a component,
|
||||
* since it has its final frame set by Yoga at this point.
|
||||
*/
|
||||
- (void)uiManagerDidPerformLayout:(RCTUIManager *)manager;
|
||||
|
||||
/**
|
||||
* Called before flushing UI blocks at the end of a batch. Note that this won't
|
||||
* get called for partial batches when using `unsafeFlushUIChangesBeforeBatchEnds`.
|
||||
* This is called from the UIManager queue. Can be used to add UI operations in that batch.
|
||||
*/
|
||||
- (void)uiManagerWillFlushUIBlocks:(RCTUIManager *)manager;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* Simple helper which take care of RCTUIManager's observers.
|
||||
*/
|
||||
@interface RCTUIManagerObserverCoordinator : NSObject <RCTUIManagerObserver>
|
||||
|
||||
/**
|
||||
* Add a UIManagerObserver. See the `RCTUIManagerObserver` protocol for more info.
|
||||
* References to observers are held weakly.
|
||||
* This method can be called safely from any queue.
|
||||
*/
|
||||
- (void)addObserver:(id<RCTUIManagerObserver>)observer;
|
||||
|
||||
/**
|
||||
* Remove a `UIManagerObserver`.
|
||||
* This method can be called safely from any queue.
|
||||
*/
|
||||
- (void)removeObserver:(id<RCTUIManagerObserver>)observer;
|
||||
|
||||
@end
|
||||
70
React/Modules/RCTUIManagerObserverCoordinator.m
Normal file
70
React/Modules/RCTUIManagerObserverCoordinator.m
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "RCTUIManagerObserverCoordinator.h"
|
||||
|
||||
#import "RCTUIManager.h"
|
||||
|
||||
@implementation RCTUIManagerObserverCoordinator {
|
||||
NSHashTable<id<RCTUIManagerObserver>> *_observers;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_observers = [[NSHashTable alloc] initWithOptions:NSHashTableWeakMemory capacity:0];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)addObserver:(id<RCTUIManagerObserver>)observer
|
||||
{
|
||||
dispatch_async(RCTGetUIManagerQueue(), ^{
|
||||
[self->_observers addObject:observer];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)removeObserver:(id<RCTUIManagerObserver>)observer
|
||||
{
|
||||
dispatch_async(RCTGetUIManagerQueue(), ^{
|
||||
[self->_observers removeObject:observer];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - RCTUIManagerObserver
|
||||
|
||||
- (void)uiManagerWillPerformLayout:(RCTUIManager *)manager
|
||||
{
|
||||
for (id<RCTUIManagerObserver> observer in _observers) {
|
||||
if ([observer respondsToSelector:@selector(uiManagerWillPerformLayout:)]) {
|
||||
[observer uiManagerWillPerformLayout:manager];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)uiManagerDidPerformLayout:(RCTUIManager *)manager
|
||||
{
|
||||
for (id<RCTUIManagerObserver> observer in _observers) {
|
||||
if ([observer respondsToSelector:@selector(uiManagerDidPerformLayout:)]) {
|
||||
[observer uiManagerDidPerformLayout:manager];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)uiManagerWillFlushUIBlocks:(RCTUIManager *)manager
|
||||
{
|
||||
for (id<RCTUIManagerObserver> observer in _observers) {
|
||||
if ([observer respondsToSelector:@selector(uiManagerWillFlushUIBlocks:)]) {
|
||||
[observer uiManagerWillFlushUIBlocks:manager];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user