91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

react-native源碼圖片緩存問題的示例分析

發布時間:2021-09-08 14:54:53 來源:億速云 閱讀:148 作者:小新 欄目:web開發

小編給大家分享一下react-native源碼圖片緩存問題的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

為xcode模擬器測試,rn版本0.44.3

突然想學習下RN是如何封裝ios中的UIImage的,看著看著發現圖片的緩存問題是個坑。。。

先看js端圖片使用的三種方式,依次排序1、2、3

 <Image source={{uri:url}} style={{width:200,height:200}}/> // 1、 加載遠程圖片
 <Image source={{uri:'1.png'}} style={{width:50,height:50}}/> //2、加載xcode中圖片
 <Image source={require('../../../Resources/Images/Contact/conact_searchIcon@3x.png')}/> //3、加載js中圖片

1、2必須設置圖片寬高,3不需設置。

對應的ios原生端文件是RCTImageViewManager,暴露的屬性

RCT_REMAP_VIEW_PROPERTY(source, imageSources, NSArray<RCTImageSource *>);

就是js中Image組件的屬性source,在js中設置source會觸發該屬性的setter方法。進入RCTImageView的

- (void)setImageSources:(NSArray<RCTImageSource *> *)imageSources
 {
   if (![imageSources isEqual:_imageSources]) {
    _imageSources = [imageSources copy];
    [self reloadImage];
   }
 }

通過此方法中斷點打印imageSources,依次得到下面結果:

react-native源碼圖片緩存問題的示例分析

可見,Image組件加載圖片都是采用URL的形式,將圖片當作網絡資源。不同的是URL的類型:

 加載網絡上圖片   : http://
 加載xcode資源   : file://
 加載js中圖片   : http://localhost:8081

追蹤setter方法,到RCTImageLoader.m中的如下方法

- (RCTImageLoaderCancellationBlock)loadImageWithURLRequest:(NSURLRequest *)imageURLRequest
              size:(CGSize)size
              scale:(CGFloat)scale
             clipped:(BOOL)clipped
            resizeMode:(RCTResizeMode)resizeMode
            progressBlock:(RCTImageLoaderProgressBlock)progressBlock
           partialLoadBlock:(RCTImageLoaderPartialLoadBlock)partialLoadBlock
           completionBlock:(RCTImageLoaderCompletionBlock)completionBlock
{
 __block volatile uint32_t cancelled = 0;
 __block dispatch_block_t cancelLoad = nil;
 dispatch_block_t cancellationBlock = ^{
 dispatch_block_t cancelLoadLocal = cancelLoad;
 if (cancelLoadLocal && !cancelled) {
  cancelLoadLocal();
 }
 OSAtomicOr32Barrier(1, &cancelled);
 };
 // 下載圖片完成后回調
 __weak RCTImageLoader *weakSelf = self;
 void (^completionHandler)(NSError *, id, BOOL, NSString *) = ^(NSError *error, id imageOrData, BOOL cacheResult, NSString *fetchDate) {
 __typeof(self) strongSelf = weakSelf;
 if (cancelled || !strongSelf) {
  return;
 }
  // 如果imageOrData是圖片類型,則直接回調
  // 此處,如果是第二種情況,則會滿足,其他情況繼續走下面方法
 if (!imageOrData || [imageOrData isKindOfClass:[UIImage class]]) {
  cancelLoad = nil;
  completionBlock(error, imageOrData);
  return;
 }
 
 // 在內存中查看是否存在該url對應的字節碼圖片
 if (cacheResult) {
  UIImage *image = [[strongSelf imageCache] imageForUrl:imageURLRequest.URL.absoluteString
              size:size
              scale:scale
             resizeMode:resizeMode
            responseDate:fetchDate];
  if (image) {
  cancelLoad = nil;
  completionBlock(nil, image);
  return;
  }
 }

  // 若沒有緩存,則將圖片解壓,再將解壓后圖片緩存block
 RCTImageLoaderCompletionBlock decodeCompletionHandler = ^(NSError *error_, UIImage *image) {
  if (cacheResult && image) {
  // Store decoded image in cache
  [[strongSelf imageCache] addImageToCache:image
            URL:imageURLRequest.URL.absoluteString
           size:size
           scale:scale
          resizeMode:resizeMode
         responseDate:fetchDate];
  }

  cancelLoad = nil;
  completionBlock(error_, image);
 };
  // 具體的解壓過程
 cancelLoad = [strongSelf decodeImageData:imageOrData
          size:size
          scale:scale
         clipped:clipped
        resizeMode:resizeMode
       completionBlock:decodeCompletionHandler];
 };
 // 走具體的方法加載圖片,1、3種情況用網絡請求下載,2情況加載本地文件
 cancelLoad = [self _loadImageOrDataWithURLRequest:imageURLRequest
            size:size
            scale:scale
           resizeMode:resizeMode
          progressBlock:progressBlock
         partialLoadBlock:partialLoadBlock
         completionBlock:completionHandler];
 return cancellationBlock;
}

具體的緩存類是RCTImageCache,采用NSCache緩存,方法

- (void)addImageToCache:(UIImage *)image
     forKey:(NSString *)cacheKey
{
 if (!image) {
 return;
 }
 CGFloat bytes = image.size.width * image.size.height * image.scale * image.scale * 4;
 if (bytes <= RCTMaxCachableDecodedImageSizeInBytes) {
 [self->_decodedImageCache setObject:image
         forKey:cacheKey
         cost:bytes];
 }
}

RCTMaxCachableDecodedImageSizeInBytes是個常量,為1048576,也就是只緩存小于1MB的圖片。

問題出在cacheKey,查看緩存key的方法

static NSString *RCTCacheKeyForImage(NSString *imageTag, CGSize size, CGFloat scale,
          RCTResizeMode resizeMode, NSString *responseDate)
{
 return [NSString stringWithFormat:@"%@|%g|%g|%g|%zd|%@",
   imageTag, size.width, size.height, scale, resizeMode, responseDate];
}

緩存key的生成方法中包含了responseDate,responseDate是網絡請求時返回來的

復制代碼 代碼如下:


responseDate = ((NSHTTPURLResponse *)response).allHeaderFields[@"Date"];

1、3方式每次加載都是一個網絡請求,那么網絡請求的時間總是變化的,于是responseDate是變化的,cacheKey不唯一,所以雖然系統做了圖片的緩存,但是每次取出的都為nil,緩存無效。

2方式加載具體方法在RCTLocalAssetImageLoader.m中,其調用的是RCTUtils的RCTImageFromLocalAssetURL方法

UIImage *__nullable RCTImageFromLocalAssetURL(NSURL *imageURL)
{
// .....省略各種處理
 UIImage *image = nil;
 if (bundle) {
 image = [UIImage imageNamed:imageName inBundle:bundle compatibleWithTraitCollection:nil];
 } else {
 image = [UIImage imageNamed:imageName];
 }
// .....省略各種處理
 return image;
}

可見是采用[UIImage imageNamed:imageName]的方式加載xcode自帶的圖片,這個是有內存緩存的。

綜上,對react-native圖片加載

1、3情況,沒有內存緩存

2情況有系統默認的內存緩存

所有情況都沒有磁盤緩存

想讓內存緩存生效,只需要改變cacheKey的生成規則即可。

補充:沙盒下面的Library/Caches/項目bunderId號/fsCachedData文件夾里面會磁盤緩存大于一定值(測試約為5kb)的圖片和文件,這個是NSURLSession網絡請求系統默認的緩存類NSURLCache自動生成的,非圖片的磁盤緩存。

以上是“react-native源碼圖片緩存問題的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

漳浦县| 巴楚县| 长乐市| 永城市| 社旗县| 邳州市| 岳普湖县| 托克托县| 海原县| 寿光市| 兴和县| 普兰县| 山东省| 平谷区| 珲春市| 左贡县| 河北区| 北票市| 英德市| 四川省| 安乡县| 喀什市| 宣威市| 湟中县| 郴州市| 苍山县| 梅河口市| 台中县| 遂宁市| 老河口市| 安仁县| 漳浦县| 碌曲县| 江陵县| 广平县| 尼勒克县| 铜梁县| 马鞍山市| 乌苏市| 益阳市| 石阡县|