最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

探究react-native 源碼的圖片緩存問題

 更新時間:2017年08月24日 15:40:10   作者:請叫我啊亮  
本篇文章主要介紹了探究react-native 源碼的圖片緩存問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

突然想學(xué)習(xí)下RN是如何封裝ios中的UIImage的,看著看著發(fā)現(xiàn)圖片的緩存問題是個坑。。。

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

 <Image source={{uri:url}} style={{width:200,height:200}}/> // 1、 加載遠(yuǎn)程圖片
 <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必須設(shè)置圖片寬高,3不需設(shè)置。

對應(yīng)的ios原生端文件是RCTImageViewManager,暴露的屬性

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

就是js中Image組件的屬性source,在js中設(shè)置source會觸發(fā)該屬性的setter方法。進(jìn)入RCTImageView的

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

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

可見,Image組件加載圖片都是采用URL的形式,將圖片當(dāng)作網(wǎng)絡(luò)資源。不同的是URL的類型:

 加載網(wǎng)絡(luò)上圖片   : 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);
 };
 // 下載圖片完成后回調(diào)
 __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是圖片類型,則直接回調(diào)
  // 此處,如果是第二種情況,則會滿足,其他情況繼續(xù)走下面方法
 if (!imageOrData || [imageOrData isKindOfClass:[UIImage class]]) {
  cancelLoad = nil;
  completionBlock(error, imageOrData);
  return;
 }
 
 // 在內(nèi)存中查看是否存在該url對應(yīng)的字節(jié)碼圖片
 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種情況用網(wǎng)絡(luò)請求下載,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是網(wǎng)絡(luò)請求時返回來的

復(fù)制代碼 代碼如下:

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

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

2方式加載具體方法在RCTLocalAssetImageLoader.m中,其調(diào)用的是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自帶的圖片,這個是有內(nèi)存緩存的。

綜上,對react-native圖片加載

1、3情況,沒有內(nèi)存緩存

2情況有系統(tǒng)默認(rèn)的內(nèi)存緩存

所有情況都沒有磁盤緩存

想讓內(nèi)存緩存生效,只需要改變cacheKey的生成規(guī)則即可。

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

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • React之錯誤邊界 Error Boundaries示例詳解

    React之錯誤邊界 Error Boundaries示例詳解

    這篇文章主要為大家介紹了React之錯誤邊界Error Boundaries示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • 淺談react-native熱更新react-native-pushy集成遇到的問題

    淺談react-native熱更新react-native-pushy集成遇到的問題

    下面小編就為大家?guī)硪黄獪\談react-native熱更新react-native-pushy集成遇到的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • React中的useState和useEffect詳細(xì)解析

    React中的useState和useEffect詳細(xì)解析

    useState和useEffect是React的兩個重要Hook,用于組件狀態(tài)管理和處理副作用,useState允許添加狀態(tài)變量,控制組件渲染,而useEffect用于執(zhí)行渲染后的副作用操作,本文給大家介紹React中的useState和useEffect詳細(xì)解析,感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • react 項目中引入圖片的幾種方式

    react 項目中引入圖片的幾種方式

    本文主要介紹了react 項目中引入圖片,本文詳細(xì)的介紹了幾種方法,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • React大文件分片上傳原理及方案

    React大文件分片上傳原理及方案

    前端進(jìn)行大文件分片上傳的方案幾乎都是利用Blob.prototype.slice方法對文件進(jìn)行分片,用數(shù)組將每一個分片存起來,最后將分片發(fā)給后端,本文給大家介紹React大文件分片上傳方案,感興趣的朋友跟隨小編一起看看吧
    2023-08-08
  • 如何深入理解React的ref 屬性

    如何深入理解React的ref 屬性

    關(guān)于 Refs ,React 官網(wǎng)講解的對于新手來說不太友好,還是自己一字一句解讀后并以代碼驗證的方式后真正理解的.
    2021-05-05
  • 淺談React雙向數(shù)據(jù)綁定原理

    淺談React雙向數(shù)據(jù)綁定原理

    在 React中是不存在雙向數(shù)據(jù)綁定的機(jī)制的,需要我們自己對其進(jìn)行實現(xiàn)。本文主要介紹一下React雙向數(shù)據(jù)綁定,感興趣的可以了解一下
    2021-11-11
  • Rust中Trait的使用

    Rust中Trait的使用

    在Rust中,Trait是一個核心概念,它允許我們定義類型應(yīng)該具有的行為,本文就來具體介紹一下Rust中Trait的使用,感興趣的可以了解一下,感興趣可以了解一下
    2024-03-03
  • React組件如何優(yōu)雅地處理異步數(shù)據(jù)詳解

    React組件如何優(yōu)雅地處理異步數(shù)據(jù)詳解

    這篇文章主要為大家介紹了React組件如何優(yōu)雅地處理異步數(shù)據(jù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • React和Vue中實現(xiàn)錨點定位功能

    React和Vue中實現(xiàn)錨點定位功能

    在React中,可以使用useState和useEffect鉤子來實現(xiàn)錨點定位功能,在Vue中,可以使用指令來實現(xiàn)錨點定位功能,在React和Vue中實現(xiàn)錨點定位功能的方法略有不同,下面我將分別介紹,文中通過代碼示例介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01

最新評論

永嘉县| 遂昌县| 恭城| 修武县| 施甸县| 小金县| 荆门市| 大竹县| 中方县| 普陀区| 天等县| 阿合奇县| 商水县| 保德县| 郑州市| 潍坊市| 塘沽区| 城口县| 松潘县| 喜德县| 巫溪县| 淮阳县| 天津市| 保亭| 日土县| 明星| 尼玛县| 临桂县| 奉节县| 大港区| 光山县| 葵青区| 武城县| 长治县| 红原县| 桐城市| 特克斯县| 西峡县| 伊通| 梅州市| 保亭|