Skip to content

Commit

Permalink
Android: Initiate image prefetching on ImageShadowNode layout (facebo…
Browse files Browse the repository at this point in the history
…ok#47932)

Summary:

This diff introduces a code path to trigger image prefetching from `ImageShadowNode::layout`.
Changelog: [Internal]

Differential Revision: D66454087
  • Loading branch information
dmytrorykun authored and facebook-github-bot committed Nov 26, 2024
1 parent 7ebe9af commit 593d573
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 12 deletions.
1 change: 1 addition & 0 deletions packages/react-native/ReactAndroid/api/ReactAndroid.api
Original file line number Diff line number Diff line change
Expand Up @@ -2638,6 +2638,7 @@ public class com/facebook/react/fabric/FabricUIManager : com/facebook/react/brid
public fun receiveEvent (IILjava/lang/String;ZLcom/facebook/react/bridge/WritableMap;IZ)V
public fun receiveEvent (ILjava/lang/String;Lcom/facebook/react/bridge/WritableMap;)V
public fun removeUIManagerEventListener (Lcom/facebook/react/bridge/UIManagerListener;)V
public fun requestImage (IILcom/facebook/react/common/mapbuffer/ReadableMapBuffer;)V
public fun resolveCustomDirectEventName (Ljava/lang/String;)Ljava/lang/String;
public fun resolveView (I)Landroid/view/View;
public fun sendAccessibilityEvent (II)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
import com.facebook.react.uimanager.events.FabricEventDispatcher;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.facebook.react.uimanager.events.SynchronousEventReceiver;
import com.facebook.react.views.image.ReactImageManager;
import com.facebook.react.views.text.TextLayoutManager;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -872,6 +873,15 @@ public void runGuarded() {
}
}

/**
* This method initiates preloading of an image specified by ImageSource. It can later be consumed
* by an ImageView.
*/
public void requestImage(int surfaceId, int reactTag, ReadableMapBuffer params) {
mMountingManager.experimental_prefetchResource(
mReactApplicationContext, ReactImageManager.REACT_CLASS, surfaceId, reactTag, params);
}

public void setBinding(FabricUIManagerBinding binding) {
mBinding = binding;
}
Expand Down Expand Up @@ -954,7 +964,6 @@ public void receiveEvent(
* @param reactTag
* @param eventName
* @param canCoalesceEvent
* @param customCoalesceKey
* @param params
* @param eventCategory
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

#include "ImageFetcher.h"
#include <react/renderer/imagemanager/conversions.h>

namespace facebook::react {

ImageFetcher::ImageFetcher(const ContextContainer::Shared& contextContainer) {
fabricUIManager_ =
contextContainer->at<jni::global_ref<jobject>>("FabricUIManager");
requestImage_ =
fabricUIManager_->getClass()
->getMethod<void(SurfaceId, Tag, JReadableMapBuffer::javaobject)>(
"requestImage");
}

ImageRequest ImageFetcher::requestImage(
const ImageSource& imageSource,
const ImageRequestParams& imageRequestParams,
SurfaceId surfaceId,
Tag tag) const {
auto serializedImageRequest =
serializeImageRequest(imageSource, imageRequestParams);

auto readableMapBuffer =
JReadableMapBuffer::createWithContents(std::move(serializedImageRequest));

requestImage_(fabricUIManager_, surfaceId, tag, readableMapBuffer.get());

auto telemetry = std::make_shared<ImageTelemetry>(surfaceId);

return {imageSource, telemetry};
}
} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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 <fbjni/fbjni.h>

#include <react/common/mapbuffer/JReadableMapBuffer.h>
#include <react/jni/ReadableNativeMap.h>
#include <react/renderer/imagemanager/ImageRequest.h>
#include <react/renderer/imagemanager/ImageRequestParams.h>
#include <react/utils/ContextContainer.h>

namespace facebook::react {

class ImageFetcher {
public:
ImageFetcher(const ContextContainer::Shared& contextContainer);

void discardImageRequest(const std::string& imageRequestCacheKey) const;

ImageRequest requestImage(
const ImageSource& imageSource,
const ImageRequestParams& imageRequestParams,
SurfaceId surfaceId,
Tag tag) const;

private:
jni::global_ref<jobject> fabricUIManager_;
jni::JMethod<void(SurfaceId, Tag, JReadableMapBuffer::javaobject)>
requestImage_;
};
} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,20 @@

#include "ImageManager.h"

#include <react/featureflags/ReactNativeFeatureFlags.h>
#include "ImageFetcher.h"

namespace facebook::react {

ImageManager::ImageManager(
const ContextContainer::Shared& /*contextContainer*/) {
// Silence unused-private-field warning.
(void)self_;
// Not implemented.
}
ImageManager::ImageManager(const ContextContainer::Shared& contextContainer)
: self_(new ImageFetcher(contextContainer)) {}

ImageManager::~ImageManager() = default;
ImageManager::~ImageManager() {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcppcoreguidelines-no-malloc"
free(self_);
#pragma clang diagnostic pop
}

ImageRequest ImageManager::requestImage(
const ImageSource& imageSource,
Expand All @@ -26,10 +30,18 @@ ImageRequest ImageManager::requestImage(

ImageRequest ImageManager::requestImage(
const ImageSource& imageSource,
SurfaceId /*surfaceId*/,
const ImageRequestParams& /*imageRequestParams*/,
Tag /* tag */) const {
return {imageSource, nullptr, {}};
SurfaceId surfaceId,
const ImageRequestParams& imageRequestParams,
Tag tag) const {
if (ReactNativeFeatureFlags::enableImagePrefetchingAndroid()) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wcppcoreguidelines-pro-type-cstyle-cast"
return ((ImageFetcher*)self_)
->requestImage(imageSource, imageRequestParams, surfaceId, tag);
#pragma clang diagnostic pop
} else {
return {imageSource, nullptr, {}};
}
}

} // namespace facebook::react

0 comments on commit 593d573

Please sign in to comment.