mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-01-12 22:50:10 +08:00
Fabric: Fixed small perf problem in RCTImageManager
Summary: This changes fix small perf problem in RCTImageManager (and layout!) saving (in my completly non-scientific tests) up to 2 ms. Maybe that's not much, but it fires during layout (and ShadowNodeTree reconsiliation processes), so it has to be very performant. Reviewed By: JoshuaGross Differential Revision: D14072077 fbshipit-source-id: 0baa54584dc3ae6a5f43be13fd152b84801c8539
This commit is contained in:
committed by
Facebook Github Bot
parent
5e0b5ff7cc
commit
b3961aff2a
@@ -47,7 +47,10 @@ rn_xplat_cxx_library(
|
||||
],
|
||||
),
|
||||
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
|
||||
fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(),
|
||||
fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags() + [
|
||||
"-DLOG_TAG=\"ReactNative\"",
|
||||
"-DWITH_FBSYSTRACE=1",
|
||||
],
|
||||
force_static = True,
|
||||
ios_deps = [
|
||||
"xplat//js:RCTImage",
|
||||
|
||||
@@ -21,8 +21,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (instancetype)initWithImageLoader:(RCTImageLoader *)imageLoader;
|
||||
|
||||
- (facebook::react::ImageRequest)requestImage:
|
||||
(const facebook::react::ImageSource &)imageSource;
|
||||
- (facebook::react::ImageRequest)requestImage:(facebook::react::ImageSource)imageSource;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
|
||||
#import "RCTImageManager.h"
|
||||
|
||||
#import <react/debug/SystraceSection.h>
|
||||
#import <react/utils/SharedFunction.h>
|
||||
|
||||
#import <React/RCTImageLoader.h>
|
||||
#import <react/imagemanager/ImageResponse.h>
|
||||
#import <react/imagemanager/ImageResponseObserver.h>
|
||||
@@ -27,56 +30,61 @@ using namespace facebook::react;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (ImageRequest)requestImage:(const ImageSource &)imageSource {
|
||||
auto imageRequest = ImageRequest(imageSource);
|
||||
- (ImageRequest)requestImage:(ImageSource)imageSource
|
||||
{
|
||||
SystraceSection s("RCTImageManager::requestImage");
|
||||
|
||||
auto imageRequest = ImageRequest(imageSource);
|
||||
auto weakObserverCoordinator =
|
||||
(std::weak_ptr<const ImageResponseObserverCoordinator>)imageRequest.getSharedObserverCoordinator();
|
||||
|
||||
NSURLRequest *request = NSURLRequestFromImageSource(imageSource);
|
||||
auto sharedCancelationFunction = SharedFunction<>();
|
||||
imageRequest.setCancelationFunction(sharedCancelationFunction);
|
||||
|
||||
auto completionBlock = ^(NSError *error, UIImage *image) {
|
||||
auto observerCoordinator = weakObserverCoordinator.lock();
|
||||
if (!observerCoordinator) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Even if an image is being loaded asynchronously on some other background thread, some other preparation
|
||||
* work (such as creating an `NSURLRequest` object and some obscure logic inside `RCTImageLoader`) can take a couple
|
||||
* of milliseconds, so we have to offload this to a separate thread. `ImageRequest` can be created as part of the
|
||||
* layout process, so it must be highly performant.
|
||||
*/
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NSURLRequest *request = NSURLRequestFromImageSource(imageSource);
|
||||
|
||||
if (image && !error) {
|
||||
auto imageResponse = ImageResponse(
|
||||
std::shared_ptr<void>((__bridge_retained void *)image, CFRelease));
|
||||
observerCoordinator->nativeImageResponseComplete(
|
||||
std::move(imageResponse));
|
||||
} else {
|
||||
observerCoordinator->nativeImageResponseFailed();
|
||||
}
|
||||
};
|
||||
auto completionBlock = ^(NSError *error, UIImage *image) {
|
||||
auto observerCoordinator = weakObserverCoordinator.lock();
|
||||
if (!observerCoordinator) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto progressBlock = ^(int64_t progress, int64_t total) {
|
||||
auto observerCoordinator = weakObserverCoordinator.lock();
|
||||
if (!observerCoordinator) {
|
||||
return;
|
||||
}
|
||||
if (image && !error) {
|
||||
auto imageResponse = ImageResponse(std::shared_ptr<void>((__bridge_retained void *)image, CFRelease));
|
||||
observerCoordinator->nativeImageResponseComplete(std::move(imageResponse));
|
||||
} else {
|
||||
observerCoordinator->nativeImageResponseFailed();
|
||||
}
|
||||
};
|
||||
|
||||
observerCoordinator->nativeImageResponseProgress(progress / (float)total);
|
||||
};
|
||||
auto progressBlock = ^(int64_t progress, int64_t total) {
|
||||
auto observerCoordinator = weakObserverCoordinator.lock();
|
||||
if (!observerCoordinator) {
|
||||
return;
|
||||
}
|
||||
|
||||
RCTImageLoaderCancellationBlock cancelationBlock =
|
||||
[_imageLoader loadImageWithURLRequest:request
|
||||
size:CGSizeMake(
|
||||
imageSource.size.width,
|
||||
imageSource.size.height)
|
||||
scale:imageSource.scale
|
||||
clipped:YES
|
||||
resizeMode:RCTResizeModeStretch
|
||||
progressBlock:progressBlock
|
||||
partialLoadBlock:nil
|
||||
completionBlock:completionBlock];
|
||||
observerCoordinator->nativeImageResponseProgress(progress / (float)total);
|
||||
};
|
||||
|
||||
std::function<void(void)> cancelationFunction = [cancelationBlock](void) {
|
||||
cancelationBlock();
|
||||
};
|
||||
RCTImageLoaderCancellationBlock cancelationBlock =
|
||||
[self->_imageLoader loadImageWithURLRequest:request
|
||||
size:CGSizeMake(imageSource.size.width, imageSource.size.height)
|
||||
scale:imageSource.scale
|
||||
clipped:YES
|
||||
resizeMode:RCTResizeModeStretch
|
||||
progressBlock:progressBlock
|
||||
partialLoadBlock:nil
|
||||
completionBlock:completionBlock];
|
||||
|
||||
imageRequest.setCancelationFunction(cancelationFunction);
|
||||
sharedCancelationFunction.assign([cancelationBlock]() { cancelationBlock(); });
|
||||
});
|
||||
|
||||
return imageRequest;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user