android - React-Native - 缓存图像的路径
问题描述
也许我的问题听起来很愚蠢,但在这里......
我们如何获取缓存图像的路径(在 iOS 和 Android 中)?
这是我的用例:我在我的应用程序上展示了一个视图,其中列出了来自网络的图像 --> 我根据用户提供的关键字从 Google 客户搜索 API 获取了一组网址......
<FlatList
style={{ width: '100%' }}
data={this.state.suggestions}
numColumns={2}
renderItem={(img) => {
return (
<TouchableOpacity onPress={() => this.selectImageHandler(img.item)} >
<Image source={{ uri: img.item.link }} />
</TouchableOpacity>
)
}}
keyExtractor={(item, index) => index.toString()}
/>
结果如下所示:
然后用户按下图像以选择它,然后需要将此图像存储在应用程序的文件夹中(Android 中的PictureDir/myappfolder/ ,iOS 中的DocumentDir/myappfolder/)...
我现在正在做的是选择图像时,我再次下载它:
selectImageHandler = (img) => {
// (... pre code ...)
RNFS.downloadFile({
fromUrl: img.link, // e.g. "http://www.url.to/the/picture.png
toFile: uri, // e.g. "file://"+PictureDir+ "/myAppFolder/picturename.jpg"
}).promise.then( res => {
// (... post code ...)
}
它工作正常!但这需要一些时间,因为它会再次下载图像,但我觉得这是两次,因为它已经下载并存储在要显示的缓存中。
所以我的问题又来了,有没有办法知道图像在缓存中的存储位置,这样当用户按下图像保存时,它不会再次下载它,而是将其从缓存文件夹中移出到应用程序的文件夹?
我说得有道理吗?还是重新下载正确的方法?
谢谢你的帮助!
解决方案
避免多次重新下载图像的一种方法可能是接管从<Image>
组件的远程 url 下载的控制权。基本上,您可以使用该方法下载远程图像RNFS.downloadFile
,然后提供本地 URI(toFile
值)作为图像源。当然,这需要更多的工作,因为我们需要创建一个包装器组件,但是这种方法还提供了在加载时控制图像显示的选项。
例如:
import React, { useState, useLayoutEffect } from 'react';
import RNFS from 'react-native-fs';
import { URL } from 'react-native-url-polyfill';
const CACHE_DIR = RNFS.DocumentDirectoryPath; // Cross-platform directory
function ImageCard ({ imgUrl }) {
const [cachedImgUrl, setCachedImgUrl] = useState(null);
const [isImageLoading, setIsImageLoading] = useState(true);
useLayoutEffect(() => {
const getCachedImageUrl = async () => {
try {
const basename = new URL(imgUrl).pathname.split('/').pop();
const localImgUrl = `file://${CACHE_DIR}/${basename}`;
if (await RNFS.exists(localCacheUrl)) {
setCachedImgUrl(localImgUrl);
} else {
const download = RNFS.downloadFile({
fromUrl: imgUrl,
toFile: localImgUrl,
});
const downloadResult = await download.promise;
if (downloadResult.status === 200) {
setCachedImgUrl(localImgUrl);
}
}
} catch (err) {
// handle error
} finally {
setIsImageLoading(false);
}
};
getCachedImageUrl();
}, [imgUrl]);
if (isImageLoading || !cachedImgUrl) {
// A better idea would be to return some `<Loader />` component, or some placeholder, like skeleton animation, etc. This is just an example.
return null;
}
return (
<Image source={{ uri: localImgUrl }} />;
);
}
该<ImageCard />
组件替换 中的普通<Image />
组件,<FlatList />
并且仅从远程图像 URL 下载一次。上面的代码是简化的,它假设您有唯一的图像名称,您可以将其用作文件系统上的标识符,并且图像 url 不包含任何搜索参数等。请谨慎并根据您的情况调整代码直接使用前需要。
推荐阅读
- python - 实现解析梯度
- python - 为什么 GNU 科学库矩阵乘法比 numpy.matmul 慢?
- python - 快速问题:在实践中使用 tfds.load 中的 shuffle_files 改组数据
- python - Python - 如何将整数加密为字母?
- r - 如何使用 dplyr 包在 R 中使用连接的数据库?
- python - Python - “NoneType”对象不可下标?
- java - 我尝试了所有解决方案,但它不起作用。在以下任何来源中都找不到插件 [id: 'com.google.gms.google-services']
- javascript - jquery验证工作,但fform没有被发布
- java - Spring JPA 存储库查询更新卡住/阻塞
- python - TypeVar 的困惑,如何键入回调函数?