diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp index 8e350f31e0a031..3b2be76a229812 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/FabricUIManagerBinding.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -641,6 +642,19 @@ void FabricUIManagerBinding::schedulerShouldRenderTransactions( if (!mountingManager) { return; } + + if (ReactNativeFeatureFlags::enableImagePrefetchingJNIBatchingAndroid()) { + auto weakImageFetcher = + scheduler_->getContextContainer()->find>( + ImageFetcherKey); + auto imageFetcher = weakImageFetcher.has_value() + ? weakImageFetcher.value().lock() + : nullptr; + if (imageFetcher != nullptr) { + imageFetcher->flushImageRequests(); + } + } + if (ReactNativeFeatureFlags::enableAccumulatedUpdatesInRawPropsAndroid()) { auto mountingTransaction = mountingCoordinator->pullTransaction( /* willPerformAsynchronously = */ true); diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageManager.h b/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageManager.h index 61c90c4efd3a8f..88b58c6313a4f1 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageManager.h +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/ImageManager.h @@ -37,6 +37,9 @@ class ImageManager { Tag tag = {}) const; private: +#ifdef ANDROID + std::shared_ptr contextContainer_{}; +#endif void *self_{}; }; diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.cpp b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.cpp index 7d7830369211d4..867e0db8b549cd 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.cpp +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.cpp @@ -8,13 +8,23 @@ #include "ImageFetcher.h" #include +#include +#include #include namespace facebook::react { +extern const char ImageFetcherKey[] = "ImageFetcher"; + ImageFetcher::ImageFetcher( std::shared_ptr contextContainer) - : contextContainer_(std::move(contextContainer)) {} + : contextContainer_(std::move(contextContainer)) +#ifdef REACT_NATIVE_DEBUG + , + threadId_(std::this_thread::get_id()) +#endif +{ +} ImageRequest ImageFetcher::requestImage( const ImageSource& imageSource, @@ -29,12 +39,20 @@ ImageRequest ImageFetcher::requestImage( auto telemetry = std::make_shared(surfaceId); - flushImageRequests(); + if (!ReactNativeFeatureFlags::enableImagePrefetchingJNIBatchingAndroid()) { + flushImageRequests(); + } - return {imageSource, telemetry}; + return ImageRequest{imageSource, telemetry}; } void ImageFetcher::flushImageRequests() { +#ifdef REACT_NATIVE_DEBUG + if (ReactNativeFeatureFlags::enableImagePrefetchingJNIBatchingAndroid()) { + assertThread(); + } +#endif + if (items_.empty()) { return; } @@ -57,4 +75,12 @@ void ImageFetcher::flushImageRequests() { items_.clear(); } +#ifdef REACT_NATIVE_DEBUG +void ImageFetcher::assertThread() const { + react_native_assert( + threadId_ != std::this_thread::get_id() && + "ImageFetcher method called from the wrong thread!"); +} +#endif + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.h b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.h index d2703995e24685..12a4cf7137a180 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.h +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageFetcher.h @@ -13,9 +13,14 @@ #include #include #include +#ifdef REACT_NATIVE_DEBUG +#include +#endif namespace facebook::react { +extern const char ImageFetcherKey[]; + class ImageFetcher { public: ImageFetcher(std::shared_ptr contextContainer); @@ -25,16 +30,22 @@ class ImageFetcher { ImageFetcher(ImageFetcher &&) = delete; ImageFetcher &operator=(ImageFetcher &&) = delete; + void flushImageRequests(); + + private: + friend class ImageManager; ImageRequest requestImage( const ImageSource &imageSource, SurfaceId surfaceId, const ImageRequestParams &imageRequestParams, Tag tag); - private: - void flushImageRequests(); - std::unordered_map> items_; std::shared_ptr contextContainer_; + +#ifdef REACT_NATIVE_DEBUG + std::thread::id threadId_; + void assertThread() const; +#endif }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageManager.cpp b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageManager.cpp index 014979f8e26bf8..9f3f848cc6fb4c 100644 --- a/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/imagemanager/platform/android/react/renderer/imagemanager/ImageManager.cpp @@ -22,10 +22,21 @@ constexpr inline bool isInteger(const std::string& str) { ImageManager::ImageManager( const std::shared_ptr& contextContainer) - : self_(new ImageFetcher(contextContainer)) {} + : contextContainer_(contextContainer), + self_(new std::shared_ptr( + std::make_shared(contextContainer))) { + if (ReactNativeFeatureFlags::enableImagePrefetchingJNIBatchingAndroid()) { + std::weak_ptr weakImageFetcher = + *static_cast*>(self_); + contextContainer->insert(ImageFetcherKey, weakImageFetcher); + } +} ImageManager::~ImageManager() { - delete static_cast(self_); + if (ReactNativeFeatureFlags::enableImagePrefetchingJNIBatchingAndroid()) { + contextContainer_->erase(ImageFetcherKey); + } + delete static_cast*>(self_); } ImageRequest ImageManager::requestImage( @@ -35,8 +46,9 @@ ImageRequest ImageManager::requestImage( Tag tag) const { if (ReactNativeFeatureFlags::enableImagePrefetchingAndroid()) { if (!isInteger(imageSource.uri)) { - return static_cast(self_)->requestImage( - imageSource, surfaceId, imageRequestParams, tag); + return static_cast*>(self_) + ->get() + ->requestImage(imageSource, surfaceId, imageRequestParams, tag); } } return {imageSource, nullptr, {}};