在Android端,React Native采用了Fresco图片库来进行图片相关的操作,因此RN所有的图片管理策略都基于Fresco。
ImageLoaderModule利用Fresco向JS端提供了图片加载相关的能力,该module主要API方法如下:
-
getSize
获取网络图片的宽高 -
prefetchImage
预加载图片到磁盘缓存 -
abortRequest
取消请求任务 -
queryCache
根据uri查询该图片的缓存位置(memory 或者 disk)
具体实现分析如下。
getSize
-
input
: 图片的URI -
output
:图片尺寸对象
{
“width”:400,
"height":300
}
getSize
异步获取网络图片的宽高:
public void getSize(
final String uriString,
final Promise promise) {
if (uriString == null || uriString.isEmpty()) {
promise.reject(ERROR_INVALID_URI, "Cannot get the size of an image for an empty URI");
return;
}
Uri uri = Uri.parse(uriString);
// 根据URI 创建图片请求对象
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).build();
// 下载图片并decode
DataSource<CloseableReference<CloseableImage>> dataSource =
Fresco.getImagePipeline().fetchDecodedImage(request, mCallerContext);
DataSubscriber<CloseableReference<CloseableImage>> dataSubscriber =
new BaseDataSubscriber<CloseableReference<CloseableImage>>() {
@Override
protected void onNewResultImpl(
DataSource<CloseableReference<CloseableImage>> dataSource) {
if (!dataSource.isFinished()) {
return;
}
CloseableReference<CloseableImage> ref = dataSource.getResult();
if (ref != null) {
try {
CloseableImage image = ref.get();
WritableMap sizes = Arguments.createMap();
sizes.putInt("width", image.getWidth());
sizes.putInt("height", image.getHeight());
promise.resolve(sizes);
} catch (Exception e) {
promise.reject(ERROR_GET_SIZE_FAILURE, e);
} finally {
CloseableReference.closeSafely(ref);
}
} else {
promise.reject(ERROR_GET_SIZE_FAILURE);
}
}
@Override
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
promise.reject(ERROR_GET_SIZE_FAILURE, dataSource.getFailureCause());
}
};
dataSource.subscribe(dataSubscriber, CallerThreadExecutor.getInstance());
}
prefetchImage
-
input
:图片的URI,标识请求的ID -
output
:图片是否预加载成功
prefetchImage
将图片下载到磁盘缓存中
public void prefetchImage(
final String uriString,
final int requestId,
final Promise promise)
{
if (uriString == null || uriString.isEmpty()) {
promise.reject(ERROR_INVALID_URI, "Cannot prefetch an image for an empty URI");
return;
}
Uri uri = Uri.parse(uriString);
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).build();
//下载图片到磁盘
DataSource<Void> prefetchSource =
Fresco.getImagePipeline().prefetchToDiskCache(request, mCallerContext);
DataSubscriber<Void> prefetchSubscriber = new BaseDataSubscriber<Void>() {
@Override
protected void onNewResultImpl(DataSource<Void> dataSource) {
if (!dataSource.isFinished()) {
return;
}
try {
removeRequest(requestId);
promise.resolve(true);
} finally {
dataSource.close();
}
}
@Override
protected void onFailureImpl(DataSource<Void> dataSource) {
try {
removeRequest(requestId);
promise.reject(ERROR_PREFETCH_FAILURE, dataSource.getFailureCause());
} finally {
dataSource.close();
}
}
};
registerRequest(requestId, prefetchSource);
prefetchSource.subscribe(prefetchSubscriber, CallerThreadExecutor.getInstance());
}
queryCache
input
: 待查询的uri 数组
output
: 图片位于缓存的位置对象
{
"https://s.geilicdn.com/CPC/common/201705/header/images/logo-5f5aeedef4.png": "disk",
"https://s.geilicdn.com/CPC/loginNew/201706/login/images/topic-bb6756e79d.png": "memory"
}
根据uri查询异步图片所在缓存类型:
public void queryCache(final ReadableArray uris, final Promise promise) {
// perform cache interrogation in async task as disk cache checks are expensive
new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
@Override
protected void doInBackgroundGuarded(Void... params) {
WritableMap result = Arguments.createMap();
ImagePipeline imagePipeline = Fresco.getImagePipeline();
for (int i = 0; i < uris.size(); i++) {
String uriString = uris.getString(i);
final Uri uri = Uri.parse(uriString);
if (imagePipeline.isInBitmapMemoryCache(uri)) {
result.putString(uriString, "memory");
} else if (imagePipeline.isInDiskCacheSync(uri)) {
result.putString(uriString, "disk");
}
}
promise.resolve(result);
}
}.executeOnExecutor(GuardedAsyncTask.THREAD_POOL_EXECUTOR);
}