反应本机AsyncStorage行太大,无法放入CursorWindow

时间:2019-07-12 21:23:38

标签: sqlite react-native asyncstorage

我在ReactNative中使用AsyncStorage在设备上存储一些数据(大尺​​寸> 2MB),然后使用以下代码读取

try {
   const value = await AsyncStorage.getItem('date_stored_copy');
} catch (e) {
   console.log(e);
}

我遇到以下错误:

  

行太大而无法容纳CursorWindow requiredPos = 0,totalRows = 1 ...

有什么方法可以增加CursorWindow的大小,还是AsyncStorage的另一种选择?

3 个答案:

答案 0 :(得分:1)

另一种解决方案是将数据分成多个块,然后写入。

我写了一个使用AsyncStorage的包装程序,该包装程序确实做到了:https://gist.github.com/bureyburey/2345dfa88a31e00a514479be37848d42

请注意,它最初是为与apollo-cache-persist(apollo客户端的持久性库)一起使用而编写的。 而且由于graphql将数据存储在非常扁平的结构中,所以该解决方案开箱即用。

对于您的情况,如果您存储的对象如下所示:

{
    data: { a lot of data here }
}

那没关系,包装程序也不会起作用

但是如果您的对象看起来像这样:

{
    someData: { partial data },
    someMoreData: { more partial data },
    ....
}

然后从理论上讲它应该起作用。

完全公开:我尚未对其进行全面测试,仅将其与apollo-cache-persist一起使用

答案 1 :(得分:1)

我也遇到了这个问题,这是我解决这个问题的方法:

算法基本描述:

  • “键”包含您的数据将被除以的部分数。 (例如:key 是“MyElementToStore”,它的值为 7,表示您的数据需要拆分以适合 AsyncStorage 一行中的每个部分)
  • 然后,每个部分将作为单独的行存储在 AsyncStorage 中,方法是将键的名称后跟部分的索引。 (例如:["MyElementToStore0", "MyElementToStore1", ...]
  • 检索数据的工作方式相反,检索每一行并聚合到结果以返回
  • 清除存储的最后注意事项,在删除密钥之前删除每个部分很重要(使用最后一个函数“clearStore”以确保正确释放内存)

AsyncStorage documentation

import AsyncStorage from "@react-native-async-storage/async-storage";

const getStore = async (key) =>
{
  try
  {
    let store = "";
    let numberOfParts = await AsyncStorage.getItem(key);
    if(typeof(numberOfParts) === 'undefined' || numberOfParts === null)
      return null;
    else
      numberOfParts = parseInt(numberOfParts);
    for (let i = 0; i < numberOfParts; i++) { store += await AsyncStorage.getItem(key + i); }
    if(store === "")
      return null;
    return JSON.parse(store);
  }
  catch (error)
  {
    console.log("Could not get [" + key + "] from store.");
    console.log(error);
    return null;
  }
};

const saveStore = async (key, data) =>
{
  try
  {
    const store = JSON.stringify(data).match(/.{1,1000000}/g);
    store.forEach((part, index) => { AsyncStorage.setItem((key + index), part); });
    AsyncStorage.setItem(key, ("" + store.length));
  }
  catch (error)
  {
    console.log("Could not save store : ");
    console.log(error.message);
  }
};

const clearStore = async (key) =>
{
  try
  {
    console.log("Clearing store for [" + key + "]");
    let numberOfParts = await AsyncStorage.getItem(key);
    if(typeof(numberOfParts) !== 'undefined' && numberOfParts !== null)
    {
      numberOfParts = parseInt(numberOfParts);
      for (let i = 0; i < numberOfParts; i++) { AsyncStorage.removeItem(key + i); }
      AsyncStorage.removeItem(key);
    }
  }
  catch (error)
  {
    console.log("Could not clear store : ");
    console.log(error.message);
  }
};

答案 2 :(得分:0)

我发现提到了另一种here

只需安装react-native-fs-store

npm i react-native-fs react-native-fs-store

react-native link react-native-fs

并像这样使用它:

import Store from "react-native-fs-store";
const AsyncStorage = new Store('store1');

它具有与AsyncStorage完全相同的API,因此无需更改代码

**请注意,react-native-fs-storeAsyncStorage慢,因为每个操作都已同步到文件。因此,您可能会在读取/写入数据时注意到延迟(屏幕无响应)