Fabric: Support for view recycling in RCTComponentViewRegistry

Summary: Quite trivial but still very cool recycling of native view instances is finnally here, in React Native. �

Reviewed By: mdvacca

Differential Revision: D7804085

fbshipit-source-id: 644804da3185f9ed3fdea42d4d76c93e86934448
This commit is contained in:
Valentin Shergin 2018-05-08 22:56:04 -07:00 committed by Facebook Github Bot
parent 6e537b000b
commit 7cf7028092
3 changed files with 54 additions and 4 deletions

View File

@ -10,8 +10,11 @@
#import <Foundation/NSMapTable.h>
#import <React/RCTAssert.h>
const NSInteger RCTComponentViewRegistryRecyclePoolMaxSize = 256;
@implementation RCTComponentViewRegistry {
NSMapTable<id, UIView<RCTComponentViewProtocol> *> *_registry;
NSMapTable<NSString *, NSHashTable<UIView<RCTComponentViewProtocol> *> *> *_recyclePool;
}
- (instancetype)init
@ -19,6 +22,8 @@
if (self = [super init]) {
_registry = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsIntegerPersonality | NSPointerFunctionsOpaqueMemory
valueOptions:NSPointerFunctionsObjectPersonality];
_recyclePool = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsObjectPersonality
valueOptions:NSPointerFunctionsObjectPersonality];
}
return self;
@ -28,9 +33,8 @@
tag:(ReactTag)tag
{
RCTAssertMainQueue();
// This is temporary approach.
NSString *className = [NSString stringWithFormat:@"RCT%@ComponentView", componentName];
UIView<RCTComponentViewProtocol> *componentView = [[NSClassFromString(className) alloc] init];
UIView<RCTComponentViewProtocol> *componentView =
[self _dequeueComponentViewWithName:componentName];
componentView.tag = tag;
[_registry setObject:componentView forKey:(__bridge id)(void *)tag];
return componentView;
@ -42,6 +46,8 @@
{
RCTAssertMainQueue();
[_registry removeObjectForKey:(__bridge id)(void *)tag];
componentView.tag = 0;
[self _enqueueComponentViewWithName:componentName componentView:componentView];
}
- (UIView<RCTComponentViewProtocol> *)componentViewByTag:(ReactTag)tag
@ -56,4 +62,45 @@
return componentView.tag;
}
- (UIView<RCTComponentViewProtocol> *)_createComponentViewWithName:(NSString *)componentName
{
RCTAssertMainQueue();
// This is temporary approach.
NSString *className = [NSString stringWithFormat:@"RCT%@ComponentView", componentName];
UIView<RCTComponentViewProtocol> *componentView = [[NSClassFromString(className) alloc] init];
return componentView;
}
- (nullable UIView<RCTComponentViewProtocol> *)_dequeueComponentViewWithName:(NSString *)componentName
{
RCTAssertMainQueue();
NSHashTable<UIView<RCTComponentViewProtocol> *> *componentViews = [_recyclePool objectForKey:componentName];
if (!componentViews || componentViews.count == 0) {
return [self _createComponentViewWithName:componentName];
}
UIView<RCTComponentViewProtocol> *componentView = [componentViews anyObject];
[componentViews removeObject:componentView];
return componentView;
}
- (void)_enqueueComponentViewWithName:(NSString *)componentName
componentView:(UIView<RCTComponentViewProtocol> *)componentView
{
RCTAssertMainQueue();
[componentView prepareForRecycle];
NSHashTable<UIView<RCTComponentViewProtocol> *> *componentViews = [_recyclePool objectForKey:componentName];
if (!componentViews) {
componentViews = [NSHashTable hashTableWithOptions:NSPointerFunctionsObjectPersonality];
[_recyclePool setObject:componentViews forKey:componentName];
}
if (componentViews.count >= RCTComponentViewRegistryRecyclePoolMaxSize) {
return;
}
[componentViews addObject:componentView];
}
@end

View File

@ -10,6 +10,7 @@
#import <React/RCTComponentViewProtocol.h>
#import <React/UIView+ComponentViewProtocol.h>
#import <fabric/core/LayoutMetrics.h>
#import <fabric/core/Props.h>
NS_ASSUME_NONNULL_BEGIN
@ -19,6 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface RCTViewComponentView : UIView <RCTComponentViewProtocol> {
@protected
facebook::react::LayoutMetrics _layoutMetrics;
facebook::react::SharedProps _props;
}
@end

View File

@ -17,8 +17,9 @@ using namespace facebook::react;
oldProps:(facebook::react::SharedProps)oldProps
{
if (!oldProps) {
oldProps = std::make_shared<ViewProps>();
oldProps = _props ?: std::make_shared<ViewProps>();
}
_props = props;
auto oldViewProps = *std::dynamic_pointer_cast<const ViewProps>(oldProps);
auto newViewProps = *std::dynamic_pointer_cast<const ViewProps>(props);