博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React Native的缓存和下载
阅读量:5151 次
发布时间:2019-06-13

本文共 5942 字,大约阅读时间需要 19 分钟。

一般我们有3种数据需要缓存和下载:纯文本(比如API返回,状态标记等),图片缓存和其他静态文件。

纯文本

纯文本还是比较简单的,RN官方模块AsyncStorage就够了。它就跟HTML5里面的LocalStorage一样,你可以直接调setItemgetItem去操作数据,这两个方法都会返回一个promise。下面是官方的例子:

缓存数据

_storeData = async () => {  try {    await AsyncStorage.setItem('@MySuperStore:key', 'I like to save it.');  } catch (error) {    // Error saving data  }};

获取数据

_retrieveData = async () => {  try {    const value = await AsyncStorage.getItem('TASKS');    if (value !== null) {      // We have data!!      console.log(value);    }  } catch (error) {    // Error retrieving data  }};

在iOS上,AsyncStorage是native代码实现的,如果是小数据,就存在一个序列化字典里面,如果数据量太大,就单独存一个文件。在Android上,AsyncStorage使用的是 或者 SQLite,取决于当前设备支持哪个。需要注意的是,Android上有大小限制,最大只能存6MB。这个是RN官方故意的,。如果需要的话,可以覆盖这个限制:

  • 找到/android/app/src/main/java/MainApplication.java 并且导入 ReactDatabaseSupplier

    import com.facebook.react.modules.storage.ReactDatabaseSupplier;

    导入后这个文件看起来像这样:

    import com.facebook.react.shell.MainReactPackage;import com.facebook.soloader.SoLoader;import com.facebook.react.modules.storage.ReactDatabaseSupplier;
  • 找到 onCreate 并设置新的 maximumSize,我这里设置为50MB

    long size = 50L * 1024L * 1024L; // 50 MB ReactDatabaseSupplier.getInstance(getApplicationContext()).setMaximumSize(size);

    改好后的onCreate看起来是这样:

    @Overridepublic void onCreate() {  super.onCreate();  SoLoader.init(this, /* native exopackage */ false);  long size = 50L * 1024L * 1024L; // 50 MB   ReactDatabaseSupplier.getInstance(getApplicationContext()).setMaximumSize(size);}

    虽然可以覆盖这个大小,但是不推荐这么做,这会让DB变得很大很丑,如果存储失败,虽然会抛错,但是数据并不会回滚,数据会更丑。如果你需要存储大的数据,你可以把它存为文件,我们后面会讲到

图片

如果一个图片我们已经加载过一次了,下次再用的时候我就不想再加载一次了,最好是直接能从缓存读出来。官方组件可以支持一些缓存,但是他只支持iOS。我这里找了两个比较流行的库 和

react-native-cached-image

你可以跟着官方指引来安装,我就不多说了。但是要注意一点,这个库依赖 。这是一个native模块,在执行yarn add 或者 npm install后,你需要把它链接到你的项目,最简单的是执行react-native link react-native-fetch-blob自动链接。如果你的项目结构跟自动链接的不一样,你需要手动链接,。

这个库有三个比较有用的组件,CachedImage, ImageCacheProviderImageCacheManager,这是一个官方例子:

import React from 'react';import {    CachedImage,    ImageCacheProvider} from 'react-native-cached-image';const images = [    'https://example.com/images/1.jpg',    'https://example.com/images/2.jpg',    'https://example.com/images/3.jpg',    // ...];export default class Example extends React.Component {    render() {        return (            
console.log('hey there')}>
); }}

ImageCacheManager是用来控制缓存的,你可以用它下载和删除图片,甚至你可以获取到下载图片的物理地址。它并没有缓存优先,强制刷新,强制使用缓存这种预设规则可以用,具体怎么用需要你自己定义。

react-native-fast-image

react-native-fast-image用起来更简单一点,在GitHub上的星星也多一点。这是一个native库,在iOS上是包装的 ,Android上是包装的,这两个都是原生上万星星的库。因为是native库,所以安装后也需要链接,具体方法跟上面一样。这是一个使用例子:

import FastImage from 'react-native-fast-image'const YourImage = () =>  

它预设了三种模式来控制缓存,其中一个是FastImage.cacheControl.web,这个策略就是网页是一样的了,他会采用HTTP的缓存控制头来控制,前端开发者应该很熟悉。这个库官方有很多例子可以看,。做图片缓存的话,推荐用这个。

其他静态文件

有时候我们需要下载或者缓存一些静态文件到设备上,比如pdf, mp3, mp4等。是一个可以将你的HTTP返回作为文件存在设备上的native库。他其实就是react-native-fetch-blob,但是react-native-fetch-blob没有继续维护了,所以就fork过来改了个名字继续维护。

你只要在请求的配置里面设置fileCache : true,他就会将返回值作为文件存起来,同时返回给你物理路径,默认存的文件是没有后缀名的,你可以加参数设定后缀,比如:appendExt : 'zip'

RNFetchBlob  .config({    // add this option that makes response data to be stored as a file,    // this is much more performant.    fileCache : true,    appendExt : 'zip'  })  .fetch('GET', 'http://www.example.com/file/example.zip', {    Authorization : 'Bearer access-token...',    //some headers ..  })  .then((res) => {    // the temp file path    console.log('The file saved to ', res.path())  })

拿到这个路径可以直接用

imageView = 

这个库还可以支持文件上传

RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {    // dropbox upload headers    Authorization : "Bearer access-token...",    'Dropbox-API-Arg': JSON.stringify({      path : '/img-from-react-native.png',      mode : 'add',      autorename : true,      mute : false    }),    'Content-Type' : 'application/octet-stream',    // Change BASE64 encoded data to a file path with prefix `RNFetchBlob-file://`.    // Or simply wrap the file path with RNFetchBlob.wrap().  }, RNFetchBlob.wrap(PATH_TO_THE_FILE))  .then((res) => {    console.log(res.text())  })  .catch((err) => {    // error handling ..  })

在下载和上传过程中,还可以拿到他的进度:

RNFetchBlob.fetch('POST', 'http://www.example.com/upload', {    //... some headers,    'Content-Type' : 'octet-stream'  }, base64DataString)  // listen to upload progress event  .uploadProgress((written, total) => {      console.log('uploaded', written / total)  })  .then((resp) => {    // ...  })  .catch((err) => {    // ...  })RNFetchBlob  .config({    // add this option that makes response data to be stored as a file,    // this is much more performant.    fileCache : true,    appendExt : 'zip'  })  .fetch('GET', 'http://www.example.com/file/example.zip', {    Authorization : 'Bearer access-token...',    //some headers ..  })  // listen to download progress event  .progress((received, total) => {      console.log('progress', received / total)  })  .then((res) => {    // the temp file path    console.log('The file saved to ', res.path())  })

要注意点的是,rn-fetch-blob并不会记录你的下载历史,就是说你关掉APP再打开,你就不知道你下载的文件哪儿去了。我们可以用AsyncStorage配合着记录下载的历史。

下载完成后记录地址到AsyncStorage

RNFetchBlob  .config({    fileCache: true,    appendExt: 'pdf',  })  .fetch('GET', 'http://pdf.dfcfw.com/pdf/H3_AP201901271289150621_1.pdf')  .then((response) => {    const path = response.path();    this.setState({      cachedFile: path,    });    AsyncStorage.setItem('fileCache', path);  })  .catch((error) => {    this.setState({      error,    });  });

检查是不是已经下过这个文件了:

componentDidMount() {  AsyncStorage.getItem('fileCache').then((data) => {    this.setState({      cachedFile: data,    });  });}

用完了也可以删除这个文件,同时删除记录

clearCache() {  const { cachedFile } = this.state;  RNFetchBlob.fs.unlink(cachedFile).then(() => {    this.setState({      cachedFile: null,    });    AsyncStorage. removeItem('fileCache');  });}

转载于:https://www.cnblogs.com/dennisj/p/10349742.html

你可能感兴趣的文章
35. Search Insert Position(C++)
查看>>
[毕业生的商业软件开发之路]C#异常处理
查看>>
一些php文件函数
查看>>
jQuery 给div绑定单击事件
查看>>
有关快速幂取模
查看>>
Linux运维必备工具
查看>>
字符串的查找删除
查看>>
NOI2018垫底记
查看>>
快速切题 poj 1002 487-3279 按规则处理 模拟 难度:0
查看>>
Codeforces Round #277 (Div. 2)
查看>>
【更新】智能手机批量添加联系人
查看>>
NYOJ-128前缀式计算
查看>>
淡定,啊。数据唯一性
查看>>
深入理解 JavaScript 事件循环(一)— event loop
查看>>
Hive(7)-基本查询语句
查看>>
注意java的对象引用
查看>>
C++ 面向对象 类成员函数this指针
查看>>
Python字符编码
查看>>
leetcode 49. 字母异位词分组(Group Anagrams)
查看>>
NSPredicate的使用,超级强大
查看>>