mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fabric: Migrate Image to State from LocalData
Summary: Changelog: [Internal] We are moving away from LocalData in favour of State. Reviewed By: shergin Differential Revision: D19247031 fbshipit-source-id: 8884133b13dd111e8d9e2cd4936bf90bfc5b4932
This commit is contained in:
committed by
Facebook Github Bot
parent
8a4f9b31b3
commit
3d6f5f50a7
@@ -11,7 +11,6 @@
|
||||
#import <React/RCTImageResponseObserverProxy.h>
|
||||
#import <react/components/image/ImageComponentDescriptor.h>
|
||||
#import <react/components/image/ImageEventEmitter.h>
|
||||
#import <react/components/image/ImageLocalData.h>
|
||||
#import <react/components/image/ImageProps.h>
|
||||
#import <react/imagemanager/ImageInstrumentation.h>
|
||||
#import <react/imagemanager/ImageRequest.h>
|
||||
@@ -26,7 +25,7 @@
|
||||
|
||||
@implementation RCTImageComponentView {
|
||||
UIImageView *_imageView;
|
||||
SharedImageLocalData _imageLocalData;
|
||||
ImageShadowNode::ConcreteState::Shared _state;
|
||||
ImageResponseObserverCoordinator const *_coordinator;
|
||||
RCTImageResponseObserverProxy _imageResponseObserverProxy;
|
||||
}
|
||||
@@ -80,34 +79,28 @@
|
||||
[super updateProps:props oldProps:oldProps];
|
||||
}
|
||||
|
||||
- (void)updateLocalData:(SharedLocalData)localData oldLocalData:(SharedLocalData)oldLocalData
|
||||
- (void)updateState:(facebook::react::State::Shared const &)state
|
||||
oldState:(facebook::react::State::Shared const &)oldState
|
||||
{
|
||||
auto imageLocalData = std::static_pointer_cast<ImageLocalData const>(localData);
|
||||
_state = std::static_pointer_cast<ImageShadowNode::ConcreteState const>(state);
|
||||
auto _oldState = std::static_pointer_cast<ImageShadowNode::ConcreteState const>(oldState);
|
||||
auto data = _state->getData();
|
||||
|
||||
// This call (setting `coordinator`) must be unconditional (at the same block as setting `LocalData`)
|
||||
// because the setter stores a raw pointer to object that `LocalData` owns.
|
||||
self.coordinator = imageLocalData ? &imageLocalData->getImageRequest().getObserverCoordinator() : nullptr;
|
||||
// This call (setting `coordinator`) must be unconditional (at the same block as setting `State`)
|
||||
// because the setter stores a raw pointer to object that `State` owns.
|
||||
self.coordinator = &data.getImageRequest().getObserverCoordinator();
|
||||
|
||||
auto previousData = _imageLocalData;
|
||||
_imageLocalData = imageLocalData;
|
||||
bool havePreviousData = _oldState && _oldState->getData().getImageSource() != ImageSource{};
|
||||
|
||||
if (!_imageLocalData) {
|
||||
// This might happen in very rare cases (e.g. inside a subtree inside a node with `display: none`).
|
||||
// That's quite normal.
|
||||
return;
|
||||
}
|
||||
|
||||
bool havePreviousData = previousData != nullptr;
|
||||
|
||||
if (!havePreviousData || _imageLocalData->getImageSource() != previousData->getImageSource()) {
|
||||
if (!havePreviousData || data.getImageSource() != _oldState->getData().getImageSource()) {
|
||||
// Loading actually starts a little before this, but this is the first time we know
|
||||
// the image is loading and can fire an event from this component
|
||||
std::static_pointer_cast<ImageEventEmitter const>(_eventEmitter)->onLoadStart();
|
||||
|
||||
// TODO (T58941612): Tracking for visibility should be done directly on this class.
|
||||
// For now, we consolidate instrumentation logic in the image loader, so that pre-Fabric gets the same treatment.
|
||||
auto instrumentation = std::static_pointer_cast<const RCTImageInstrumentationProxy>(
|
||||
_imageLocalData->getImageRequest().getSharedImageInstrumentation());
|
||||
auto instrumentation = std::static_pointer_cast<RCTImageInstrumentationProxy const>(
|
||||
data.getImageRequest().getSharedImageInstrumentation());
|
||||
instrumentation->trackNativeImageView(self);
|
||||
}
|
||||
}
|
||||
@@ -128,7 +121,7 @@
|
||||
[super prepareForRecycle];
|
||||
self.coordinator = nullptr;
|
||||
_imageView.image = nil;
|
||||
_imageLocalData.reset();
|
||||
_state.reset();
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
@@ -171,7 +164,7 @@
|
||||
self->_imageView.layer.minificationFilter = kCAFilterTrilinear;
|
||||
self->_imageView.layer.magnificationFilter = kCAFilterTrilinear;
|
||||
|
||||
_imageLocalData->getImageRequest().getImageInstrumentation().didSetImage();
|
||||
_state->getData().getImageRequest().getImageInstrumentation().didSetImage();
|
||||
}
|
||||
|
||||
- (void)didReceiveProgress:(float)progress fromObserver:(void const *)observer
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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 "ImageLocalData.h"
|
||||
|
||||
#include <react/components/image/conversions.h>
|
||||
#include <react/debug/debugStringConvertibleUtils.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
ImageSource ImageLocalData::getImageSource() const {
|
||||
return imageSource_;
|
||||
}
|
||||
|
||||
const ImageRequest &ImageLocalData::getImageRequest() const {
|
||||
return imageRequest_;
|
||||
}
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
#if RN_DEBUG_STRING_CONVERTIBLE
|
||||
std::string ImageLocalData::getDebugName() const {
|
||||
return "ImageLocalData";
|
||||
}
|
||||
|
||||
SharedDebugStringConvertibleList ImageLocalData::getDebugProps() const {
|
||||
return {debugStringConvertibleItem("imageSource", imageSource_)};
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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 <react/core/LocalData.h>
|
||||
#include <react/imagemanager/ImageRequest.h>
|
||||
#include <react/imagemanager/primitives.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class ImageLocalData;
|
||||
|
||||
using SharedImageLocalData = std::shared_ptr<const ImageLocalData>;
|
||||
|
||||
/*
|
||||
* LocalData for <Image> component.
|
||||
* Represents the image request state and (possible) retrieved image bitmap.
|
||||
*/
|
||||
class ImageLocalData : public LocalData {
|
||||
public:
|
||||
ImageLocalData(const ImageSource &imageSource, ImageRequest imageRequest)
|
||||
: imageSource_(imageSource), imageRequest_(std::move(imageRequest)){};
|
||||
|
||||
/*
|
||||
* Returns stored ImageSource object.
|
||||
*/
|
||||
ImageSource getImageSource() const;
|
||||
|
||||
/*
|
||||
* Exposes for reading stored `ImageRequest` object.
|
||||
* `ImageRequest` object cannot be copied or moved from `ImageLocalData`.
|
||||
*/
|
||||
const ImageRequest &getImageRequest() const;
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
#if RN_DEBUG_STRING_CONVERTIBLE
|
||||
std::string getDebugName() const override;
|
||||
SharedDebugStringConvertibleList getDebugProps() const override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
ImageSource imageSource_;
|
||||
ImageRequest imageRequest_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -8,9 +8,9 @@
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
|
||||
#include <react/components/image/ImageLocalData.h>
|
||||
#include <react/components/image/ImageShadowNode.h>
|
||||
#include <react/core/LayoutContext.h>
|
||||
#include "ImageState.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
@@ -22,27 +22,19 @@ void ImageShadowNode::setImageManager(const SharedImageManager &imageManager) {
|
||||
imageManager_ = imageManager;
|
||||
}
|
||||
|
||||
void ImageShadowNode::updateLocalData() {
|
||||
const auto &imageSource = getImageSource();
|
||||
const auto ¤tLocalData = getLocalData();
|
||||
if (currentLocalData) {
|
||||
assert(std::dynamic_pointer_cast<const ImageLocalData>(currentLocalData));
|
||||
auto currentImageLocalData =
|
||||
std::static_pointer_cast<const ImageLocalData>(currentLocalData);
|
||||
if (currentImageLocalData->getImageSource() == imageSource) {
|
||||
// Same `imageSource` is already in `localData`,
|
||||
// no need to (re)request an image resource.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we are about to mutate the Shadow Node.
|
||||
void ImageShadowNode::updateStateIfNeeded() {
|
||||
ensureUnsealed();
|
||||
|
||||
auto imageRequest = imageManager_->requestImage(imageSource, getSurfaceId());
|
||||
auto imageLocalData =
|
||||
std::make_shared<ImageLocalData>(imageSource, std::move(imageRequest));
|
||||
setLocalData(imageLocalData);
|
||||
auto const &imageSource = getImageSource();
|
||||
auto const ¤tState = getStateData();
|
||||
|
||||
if (currentState.getImageSource() == imageSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto state = ImageState{
|
||||
imageSource, imageManager_->requestImage(imageSource, getSurfaceId())};
|
||||
setStateData(std::move(state));
|
||||
}
|
||||
|
||||
ImageSource ImageShadowNode::getImageSource() const {
|
||||
@@ -86,7 +78,7 @@ ImageSource ImageShadowNode::getImageSource() const {
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
void ImageShadowNode::layout(LayoutContext layoutContext) {
|
||||
updateLocalData();
|
||||
updateStateIfNeeded();
|
||||
ConcreteViewShadowNode::layout(layoutContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <react/components/image/ImageEventEmitter.h>
|
||||
#include <react/components/image/ImageProps.h>
|
||||
#include <react/components/image/ImageState.h>
|
||||
#include <react/components/view/ConcreteViewShadowNode.h>
|
||||
#include <react/imagemanager/ImageManager.h>
|
||||
#include <react/imagemanager/primitives.h>
|
||||
@@ -24,7 +25,8 @@ extern const char ImageComponentName[];
|
||||
class ImageShadowNode final : public ConcreteViewShadowNode<
|
||||
ImageComponentName,
|
||||
ImageProps,
|
||||
ImageEventEmitter> {
|
||||
ImageEventEmitter,
|
||||
ImageState> {
|
||||
public:
|
||||
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
||||
|
||||
@@ -38,14 +40,11 @@ class ImageShadowNode final : public ConcreteViewShadowNode<
|
||||
void layout(LayoutContext layoutContext) override;
|
||||
|
||||
private:
|
||||
/*
|
||||
* (Re)Creates a `LocalData` object (with `ImageRequest`) if needed.
|
||||
*/
|
||||
void updateLocalData();
|
||||
|
||||
ImageSource getImageSource() const;
|
||||
|
||||
SharedImageManager imageManager_;
|
||||
|
||||
void updateStateIfNeeded();
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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 "ImageState.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
ImageSource ImageState::getImageSource() const {
|
||||
return imageSource_;
|
||||
}
|
||||
|
||||
ImageRequest const &ImageState::getImageRequest() const {
|
||||
return *imageRequest_;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 <folly/dynamic.h>
|
||||
#include <react/imagemanager/ImageRequest.h>
|
||||
#include <react/imagemanager/primitives.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* State for <Image> component.
|
||||
*/
|
||||
class ImageState final {
|
||||
public:
|
||||
ImageState(ImageSource const &imageSource, ImageRequest imageRequest)
|
||||
: imageSource_(imageSource),
|
||||
imageRequest_(
|
||||
std::make_shared<ImageRequest>(std::move(imageRequest))){};
|
||||
|
||||
ImageState() = default;
|
||||
|
||||
/*
|
||||
* Returns stored ImageSource object.
|
||||
*/
|
||||
ImageSource getImageSource() const;
|
||||
|
||||
/*
|
||||
* Exposes for reading stored `ImageRequest` object.
|
||||
* `ImageRequest` object cannot be copied or moved from `ImageLocalData`.
|
||||
*/
|
||||
ImageRequest const &getImageRequest() const;
|
||||
|
||||
#ifdef ANDROID
|
||||
ImageState(ImageState const &previousState, folly::dynamic data){};
|
||||
|
||||
/*
|
||||
* Empty implementation for Android because it doesn't use this class.
|
||||
*/
|
||||
folly::dynamic getDynamic() const {
|
||||
return {};
|
||||
};
|
||||
#endif
|
||||
|
||||
private:
|
||||
ImageSource imageSource_;
|
||||
std::shared_ptr<ImageRequest> imageRequest_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
Reference in New Issue
Block a user