<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

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

        來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 22:31:55
        文檔

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

        探究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,h
        推薦度:
        導(dǎo)讀探究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,h

        本文為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、 加載遠程圖片
         <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方法。進入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ò)請求時返回來的

        代碼如下:
        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ī)則即可。

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

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

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

        探究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,h
        推薦度:
        標(biāo)簽: 圖片 的圖片 緩存
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 成全在线观看免费观看大全| 久99久精品免费视频热77| 亚洲精品动漫免费二区| 麻豆一区二区三区蜜桃免费| 全黄大全大色全免费大片| 久久久久国产精品免费免费搜索| 精品国产麻豆免费网站| 国产亚洲情侣一区二区无| 亚洲日韩图片专区第1页| 波多野结衣亚洲一级| 好吊色永久免费视频大全| 无码精品A∨在线观看免费| 全部免费a级毛片| 2017亚洲男人天堂一| 成年男女免费视频网站| 亚洲天堂中文字幕| 性xxxxx免费视频播放| 亚洲综合一区无码精品| 中国xxxxx高清免费看视频| 亚洲国产中文v高清在线观看| 亚洲人成电影网站| 久久永久免费人妻精品| 中文字幕亚洲无线码| 国产91成人精品亚洲精品| 永久免费AV无码国产网站| 久久精品亚洲中文字幕无码麻豆 | jizz免费一区二区三区| 无码人妻一区二区三区免费手机 | 亚洲精品NV久久久久久久久久| 天堂亚洲免费视频| 日韩高清在线高清免费| 亚洲乱码一二三四区乱码| 免费国产成人高清在线观看麻豆| 三级毛片在线免费观看| 亚洲日韩在线中文字幕第一页| 国产成人综合亚洲绿色| 亚洲AV日韩AV天堂一区二区三区| 一级人做人a爰免费视频| 亚洲高清免费视频| 国产亚洲精品美女| 91情国产l精品国产亚洲区|