- 缓存图像的路径,android,ios,react-native,caching"/>

首页 > 解决方案 > 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 ...)
}

它工作正常!但这需要一些时间,因为它会再次下载图像,但我觉得这是两次,因为它已经下载并存储在要显示的缓存中。

所以我的问题又来了,有没有办法知道图像在缓存中的存储位置,这样当用户按下图像保存时,它不会再次下载它,而是将从缓存文件夹中移出到应用程序的文件夹?

我说得有道理吗?还是重新下载正确的方法?

谢谢你的帮助!

标签: androidiosreact-nativecaching

解决方案


避免多次重新下载图像的一种方法可能是接管从<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 不包含任何搜索参数等。请谨慎并根据您的情况调整代码直接使用前需要。


推荐阅读