Skip to content

Commit 544f3b3

Browse files
Android: Schedule image prefetching on tree commit (#53491)
Summary: Pull Request resolved: #53491 Changelog: [Internal] Reviewed By: lenaic, cipolleschi Differential Revision: D81106112 fbshipit-source-id: b06643312836bd018bfc9a1565b76976cd55dac9
1 parent 83e1981 commit 544f3b3

5 files changed

Lines changed: 112 additions & 8 deletions

File tree

packages/react-native/ReactCommon/react/renderer/components/image/ImageShadowNode.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8+
#include "ImageState.h"
9+
810
#include <cstdlib>
911
#include <limits>
1012

13+
#include <react/featureflags/ReactNativeFeatureFlags.h>
1114
#include <react/renderer/components/image/ImageShadowNode.h>
1215
#include <react/renderer/core/LayoutContext.h>
1316
#include <react/renderer/imagemanager/ImageRequestParams.h>
14-
#include "ImageState.h"
1517

1618
namespace facebook::react {
1719

@@ -28,7 +30,8 @@ void ImageShadowNode::setImageManager(
2830
// layout, if the image source was changed we have to initiate the image
2931
// request now since there is no guarantee that layout will run for the shadow
3032
// node at a later time.
31-
if (getIsLayoutClean()) {
33+
if (getIsLayoutClean() ||
34+
ReactNativeFeatureFlags::enableImagePrefetchingAndroid()) {
3235
auto sources = getConcreteProps().sources;
3336
auto layoutMetric = getLayoutMetrics();
3437
if (sources.size() <= 1 ||

packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.cpp

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,38 @@
77

88
#include "ImageFetcher.h"
99

10+
#include <glog/logging.h>
1011
#include <react/common/mapbuffer/JReadableMapBuffer.h>
1112
#include <react/renderer/imagemanager/conversions.h>
1213

1314
namespace facebook::react {
1415

16+
ImageFetcher::ImageFetcher(
17+
std::shared_ptr<const ContextContainer> contextContainer)
18+
: contextContainer_(std::move(contextContainer)) {
19+
if (contextContainer_ != nullptr) {
20+
if (auto uiManagerCommitHookManager =
21+
contextContainer_
22+
->find<std::shared_ptr<UIManagerCommitHookManager>>(
23+
std::string(UIManagerCommitHookManagerKey));
24+
uiManagerCommitHookManager.has_value()) {
25+
(*uiManagerCommitHookManager)->registerCommitHook(*this);
26+
}
27+
}
28+
}
29+
30+
ImageFetcher::~ImageFetcher() {
31+
if (contextContainer_ != nullptr) {
32+
if (auto uiManagerCommitHookManager =
33+
contextContainer_
34+
->find<std::shared_ptr<UIManagerCommitHookManager>>(
35+
std::string(UIManagerCommitHookManagerKey));
36+
uiManagerCommitHookManager.has_value()) {
37+
(*uiManagerCommitHookManager)->unregisterCommitHook(*this);
38+
}
39+
}
40+
}
41+
1542
ImageRequest ImageFetcher::requestImage(
1643
const ImageSource& imageSource,
1744
SurfaceId surfaceId,
@@ -23,6 +50,20 @@ ImageRequest ImageFetcher::requestImage(
2350
.imageRequestParams = imageRequestParams,
2451
.tag = tag});
2552

53+
auto telemetry = std::make_shared<ImageTelemetry>(surfaceId);
54+
55+
return {imageSource, telemetry};
56+
}
57+
58+
RootShadowNode::Unshared ImageFetcher::shadowTreeWillCommit(
59+
const ShadowTree& /*shadowTree*/,
60+
const RootShadowNode::Shared& /*oldRootShadowNode*/,
61+
const RootShadowNode::Unshared& newRootShadowNode,
62+
const ShadowTree::CommitOptions& /*commitOptions*/) noexcept {
63+
if (items_.empty()) {
64+
return newRootShadowNode;
65+
}
66+
2667
auto fabricUIManager_ =
2768
contextContainer_->at<jni::global_ref<jobject>>("FabricUIManager");
2869
static auto prefetchResources =
@@ -35,9 +76,7 @@ ImageRequest ImageFetcher::requestImage(
3576
items_.clear();
3677
prefetchResources(fabricUIManager_, "RCTImageView", readableMapBuffer.get());
3778

38-
auto telemetry = std::make_shared<ImageTelemetry>(surfaceId);
39-
40-
return {imageSource, telemetry};
79+
return newRootShadowNode;
4180
}
4281

4382
} // namespace facebook::react

packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,41 @@
77

88
#pragma once
99

10+
#include <react/featureflags/ReactNativeFeatureFlags.h>
1011
#include <react/renderer/imagemanager/ImageRequest.h>
1112
#include <react/renderer/imagemanager/ImageRequestParams.h>
13+
#include <react/renderer/mounting/ShadowTree.h>
14+
#include <react/renderer/uimanager/UIManagerCommitHook.h>
1215
#include <react/utils/ContextContainer.h>
1316

1417
namespace facebook::react {
1518

16-
class ImageFetcher {
19+
class ImageFetcher : public UIManagerCommitHook {
1720
public:
18-
ImageFetcher(std::shared_ptr<const ContextContainer> contextContainer)
19-
: contextContainer_(std::move(contextContainer)) {}
21+
ImageFetcher(std::shared_ptr<const ContextContainer> contextContainer);
22+
~ImageFetcher() override;
23+
ImageFetcher(const ImageFetcher&) = delete;
24+
ImageFetcher& operator=(const ImageFetcher&) = delete;
25+
ImageFetcher(ImageFetcher&&) = delete;
26+
ImageFetcher& operator=(ImageFetcher&&) = delete;
2027

2128
ImageRequest requestImage(
2229
const ImageSource& imageSource,
2330
SurfaceId surfaceId,
2431
const ImageRequestParams& imageRequestParams,
2532
Tag tag);
2633

34+
void commitHookWasRegistered(const UIManager& uiManager) noexcept override {}
35+
36+
void commitHookWasUnregistered(const UIManager& uiManager) noexcept override {
37+
}
38+
39+
RootShadowNode::Unshared shadowTreeWillCommit(
40+
const ShadowTree& shadowTree,
41+
const RootShadowNode::Shared& oldRootShadowNode,
42+
const RootShadowNode::Unshared& newRootShadowNode,
43+
const ShadowTree::CommitOptions& commitOptions) noexcept override;
44+
2745
private:
2846
std::vector<ImageRequestItem> items_;
2947
std::shared_ptr<const ContextContainer> contextContainer_;

packages/react-native/ReactCommon/react/renderer/scheduler/Scheduler.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,33 @@
2424

2525
namespace facebook::react {
2626

27+
namespace {
28+
29+
class UIManagerCommitHookManagerImpl : public UIManagerCommitHookManager {
30+
public:
31+
explicit UIManagerCommitHookManagerImpl(std::weak_ptr<UIManager> uiManager)
32+
: uiManager_(std::move(uiManager)) {}
33+
34+
~UIManagerCommitHookManagerImpl() override = default;
35+
36+
void registerCommitHook(UIManagerCommitHook& commitHook) override {
37+
if (auto uiManager = uiManager_.lock()) {
38+
uiManager->registerCommitHook(commitHook);
39+
}
40+
}
41+
42+
void unregisterCommitHook(UIManagerCommitHook& commitHook) override {
43+
if (auto uiManager = uiManager_.lock()) {
44+
uiManager->unregisterCommitHook(commitHook);
45+
}
46+
}
47+
48+
private:
49+
std::weak_ptr<UIManager> uiManager_;
50+
};
51+
52+
} // namespace
53+
2754
Scheduler::Scheduler(
2855
const SchedulerToolbox& schedulerToolbox,
2956
UIManagerAnimationDelegate* animationDelegate,
@@ -49,6 +76,12 @@ Scheduler::Scheduler(
4976

5077
auto uiManager =
5178
std::make_shared<UIManager>(runtimeExecutor_, contextContainer_);
79+
if (ReactNativeFeatureFlags::enableImagePrefetchingAndroid()) {
80+
contextContainer_->insert(
81+
std::string(UIManagerCommitHookManagerKey),
82+
std::make_shared<UIManagerCommitHookManagerImpl>(uiManager));
83+
}
84+
5285
auto eventOwnerBox = std::make_shared<EventBeat::OwnerBox>();
5386
eventOwnerBox->owner = eventDispatcher_;
5487

packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerCommitHook.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,15 @@ class UIManagerCommitHook {
5757
virtual ~UIManagerCommitHook() noexcept = default;
5858
};
5959

60+
constexpr std::string_view UIManagerCommitHookManagerKey =
61+
"UIManagerCommitHookManager";
62+
63+
class UIManagerCommitHookManager {
64+
public:
65+
virtual ~UIManagerCommitHookManager() = default;
66+
67+
virtual void registerCommitHook(UIManagerCommitHook& commitHook) = 0;
68+
virtual void unregisterCommitHook(UIManagerCommitHook& commitHook) = 0;
69+
};
70+
6071
} // namespace facebook::react

0 commit comments

Comments
 (0)