如何在我的flutter应用程序中使用预先填充的sqlite数据库

Mar*_*arc 6 sqlite mobile flutter

正如标题中的问题所说.

我的数据库文件可能非常大,所以我不想不必要地复制它,我当然不想在原位构建它.

如果db文件是一个颤动的资产,sqlite有没有办法直接访问它?

我已经看到了一些建议,我应该将资产的原始数据复制到文件中,然后访问它,但这会浪费存储空间.或者我可以删除资产吗?

有没有一种简单的方法将数据库部署为资源以外的其他东西,即作为原始文件?

Mik*_*ahy 11

iOS(以及我认为,Android?)会要求您先将文件复制到应用程序的工作目录中.这是标准做法,它是在受保护文件系统中工作的一部分.如果以某种方式在你的应用程序包(考虑这是原始的"主")和应用程序文档文件夹("工作副本")中拥有副本是一个交易杀手,我想你也可以在初始应用程序启动时从服务器下载它,但是......时间就是金钱.

不过,这真的不是那么大的交易.为此,请通过pubspec.yaml文件确保应用程序包中包含的文件:

flutter:
  assets:
    - assets/stored_data.db
Run Code Online (Sandbox Code Playgroud)

然后,在打开数据库之前,将其从应用程序包复制到您的文档目录:

编辑:以下显然无法复制大文件; 如果您遇到此类问题,请参阅下面的iKK评论,因为看起来他找到了原生解决方案.但是,对于较小的文件,这应该可以正常工作.

// Create a new file within your document directory (Probably want to check whether it already exists first...)

Directory documentsDirectory = await getApplicationDocumentsDirectory();
String path = join(documentsDirectory.path, "working_data.db");

ByteData data = await rootBundle.load(join("assets", "stored_data.db"));
List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
await new File(path).writeAsBytes(bytes);
Run Code Online (Sandbox Code Playgroud)

现在您的应用程序文档目录中有数据库,您应该可以从path.如果您使用tekartik/sqflite包(这是我最初获得这些说明的地方)打开它,例如,您可以简单地:

Database db = await openDatabase(path); // Opens SQL database, working_data.db
Run Code Online (Sandbox Code Playgroud)

没有理由(或能力)从应用程序包中删除原始副本(这将改变原始二进制文件 - 一个巨大的 nono).最终,操作系统本身最终可能会将此类故障卸载到云服务器或其他内存管理服务,但这是由平台决定的.

  • 不错 - 但不幸的是 `rootBundle.load(join("assets", "mydb.db"));` 不适用于大型 db 文件(...即我的 &gt; 665 MB)。除了为每个世界创建本机插件的路径之外,还有其他选择吗? (2认同)
  • 最终使用 Flutter 插件解决了这个问题,该插件本地执行大文件复制(分别在 iOS 和 Android 中) - [在此处查看我的解决方案](/sf/answers/3794258191/) 或作为 @ mm2001 上面提到的,[this](https://github.com/jgilfelt/android-sqlite-asset-helper) 也可能有帮助... (2认同)