最近一個項目RN版本是0.61此熬,因里面有個圖片瀏覽功能甜刻,要做一個清理緩存的功能呻袭。一番搗鼓后功能解決顿天,記錄如下
找到的清理緩存組建是react-native-http-cache堂氯,因為該組建長期沒人維護android編譯不過,本人又不善長android露氮,遂找了個進化版react-native-http-cache3祖灰。這個在安卓上面需要更改兩個地方才可正常工作,不做討論畔规,本文主要是講ios上面。
iOS在解決了2個bug之后這個組建也能使用恨统,但是發(fā)現(xiàn)ios導給rn的方法getImageCacheSize以及clearImageCache都只是空實現(xiàn)叁扫,沒有具體內(nèi)容。原因下面解釋畜埋。
三年前我寫的分析RN端圖片緩存的策略(http://www.reibang.com/p/c7376db9b7ec)莫绣,當時圖片是沒有磁盤緩存的,內(nèi)存緩存也無效∮瓢埃現(xiàn)在再看下新的RN版本圖片緩存相關(guān)代碼对室,經(jīng)過測試發(fā)現(xiàn),對解壓后2M以內(nèi)的圖片,內(nèi)存緩存生效掩宜。磁盤緩存依舊沒有蔫骂。正因為沒有磁盤緩存,所謂的清理圖片緩存也就不存在牺汤,于是方法為空實現(xiàn)也就能理解了辽旋。
本人項目中有圖片瀏覽功能,當預覽圖片時圖片是高清的原圖檐迟,比較大补胚,按照rn默認的行為圖片不做緩存,那么每次預覽時都會去下載追迟,很緩慢溶其,影響體驗。而且因為圖片遠大于2M內(nèi)存緩存也無法生效敦间,效果很差勁瓶逃。這里需要自定義圖片的緩存
網(wǎng)上搜索了一圈發(fā)現(xiàn)都是解決方案都是使用react-native-img-cache,但是要求使用特定的<CachedImage />圖片組件每瞒,這樣是不太理想的金闽,比如我這里使用的圖片預覽組件,其內(nèi)部使用的是Animate.Image顯示圖片剿骨,總不能去別個組件內(nèi)部更改為CachedImage吧代芜。
翻看RN圖片加載相關(guān)的代碼,發(fā)現(xiàn)了關(guān)鍵地方浓利。在RCTImageLoaderProtocol.h這個圖片加載相關(guān)的協(xié)議里面發(fā)現(xiàn)
/**
* Allows developers to set their own caching implementation for
* decoded images as long as it conforms to the RCTImageCache
* protocol. This method should be called in bridgeDidInitializeModule.
*/
- (void)setImageCache:(id<RCTImageCache>)cache;
很明顯挤庇,這里可以讓開發(fā)者自定義圖片的緩存類,只需實現(xiàn)RCTImageCache協(xié)議即可贷掖。
很簡單嫡秕,我使用SDWebImage實現(xiàn)了這個協(xié)議
#import "PSImageCache.h"
#import <SDWebImage/SDImageCache.h>
@implementation PSImageCache
- (UIImage *)imageForUrl:(NSString *)url
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(RCTResizeMode)resizeMode{
if (!url) return nil;
return [[SDImageCache sharedImageCache] imageFromCacheForKey:url];
}
- (void)addImageToCache:(UIImage *)image
URL:(NSString *)url
size:(CGSize)size
scale:(CGFloat)scale
resizeMode:(RCTResizeMode)resizeMode
response:(NSURLResponse *)response{
if (!image || !url) return;
[[SDImageCache sharedImageCache] storeImage:image forKey:url completion:nil];
}
@end
現(xiàn)在只需要在一個合適的時機,將自定義的PSImageCache類賦值給RCTImageLoader即可苹威。
多方實驗昆咽,如下最佳實踐。在didFinishLaunchingWithOptions中
// 監(jiān)聽RCTImageLoader模塊加載完畢牙甫,自定義imageCache為sdwebimage緩存圖片
[[NSNotificationCenter defaultCenter] addObserverForName:RCTDidInitializeModuleNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
RCTImageLoader *imageLoader = note.userInfo[@"module"];
if ([imageLoader isKindOfClass:[RCTImageLoader class]]) {
[imageLoader setImageCache:[PSImageCache new]];
}
}];
現(xiàn)在圖片緩存已經(jīng)走Sdwebcache通道了掷酗,一切正常。最上面說的清理緩存的兩個空方法需要更改下窟哺。將Podfile中倒入的react-native-http-cache3刪除泻轰,RNHttpCache文件挪到本地文件,修改getImageCacheSize和clearImageCache方法
RCT_EXPORT_METHOD(getImageCacheSize:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
{
resolve(@([[SDImageCache sharedImageCache] totalDiskSize]));
}
RCT_EXPORT_METHOD(clearImageCache:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
{
[[SDImageCache sharedImageCache] clearDiskOnCompletion:^{
resolve(nil);
}];
}
大功告成且轨!