react-native 소스 코드 의 이미지 캐 시 문 제 를 탐구 합 니 다.
갑자기 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/[email protected]')}/> //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 인쇄 를 중단 하고 다음 결 과 를 얻 을 수 있 습 니 다.이미지 구성 요소 가 그림 을 불 러 오 는 것 은 URL 형식 으로 그림 을 네트워크 자원 으로 사용 하 는 것 을 알 수 있 습 니 다.다른 것 은 URL 의 종류 입 니 다:
: http://
xcode : file://
js : http://localhost:8081
setter 추적 방법,RCTImage Loader.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];
}
}
RCTmax CachableDecoded Image SizeInBytes 는 상수 로 1048576,즉 1MB 이하 의 그림 만 캐 시 합 니 다.문 제 는 캐 시 키 에서 캐 시 키 를 보 는 방법 입 니 다.
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];
}
캐 시 키 생 성 방법 에는 responseDate 가 포함 되 어 있 습 니 다.responseDate 는 네트워크 요청 시 되 돌아 오 는 것 입 니 다.
responseDate = ((NSHTTPURLResponse *)response).allHeaderFields[@"Date"];
1,3 방식 은 불 러 올 때마다 네트워크 요청 입 니 다.그러면 네트워크 요청 시간 은 항상 변 합 니 다.그래서 responseDate 는 변 합 니 다.cacheKey 는 유일 하지 않 기 때문에 시스템 이 그림 의 캐 시 를 만 들 었 지만 꺼 낼 때마다 nil 이 고 캐 시 는 유효 하지 않 습 니 다.2.구체 적 인 방법 은 RCTLocalAsset ImageLoader.m 에서 RCTUtils 의 RCTImage FromLocalAsset URL 방법 을 호출 합 니 다.
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 번호/fsCacheddeata 폴 더 에 일정 값(약 5kb 테스트)이상 의 그림 과 파일 이 들 어 있 습 니 다.이것 은 NSURLSession 네트워크 요청 시스템 의 기본 캐 시 클래스 NSURLCache 에서 자동 으로 생 성 되 며 그림 이 아 닌 디스크 캐 시 입 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
nginx 에서 사이트 아이콘 표시 설정전단 개발 환경: react:^16.4.1 webpack:^4.16.0 웹 팩 에 favicon. ico 설정 추가: nginx 는 ico 에 대한 지원 을 추가 합 니 다:...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.