在 Android 应用程序中对 SQLite 数据库执行查询时,最佳实践是什么?
从 AsyncTask 的 doInBackground 运行插入、删除和选择查询是否安全?还是我应该使用 UI 线程?我认为数据库查询可能是“繁重的”并且不应该使用 UI 线程,因为它可以锁定应用程序 - 导致应用程序无响应(ANR)。
如果我有多个 AsyncTask,它们应该共享一个连接还是应该各自打开一个连接?
这些场景是否有任何最佳实践?
从多个线程中插入、更新、删除和读取通常是可以的,但布拉德的答案是不正确的。您必须小心创建和使用连接的方式。即使您的数据库没有损坏,在某些情况下您的更新调用也会失败。
基本答案。
SqliteOpenHelper 对象保持一个数据库连接。它似乎为您提供了读写连接,但实际上并没有。调用只读,无论如何你都会得到写数据库连接。
所以,一个助手实例,一个数据库连接。即使您从多个线程中使用它,一次一个连接。SqliteDatabase 对象使用 java 锁来保持访问序列化。因此,如果 100 个线程有一个 db 实例,则对实际磁盘数据库的调用将被序列化。
所以,一个助手,一个数据库连接,它是用java代码序列化的。一个线程,1000 个线程,如果您使用它们之间共享的一个帮助程序实例,那么您所有的数据库访问代码都是串行的。生活是美好的(ish)。
如果您尝试同时从实际的不同连接写入数据库,则会失败。它不会等到第一个完成后再写入。它根本不会写你的改变。更糟糕的是,如果您没有在 SQLiteDatabase 上调用正确版本的插入/更新,您将不会获得异常。您只需在 LogCat 中收到一条消息,就可以了。
那么,多线程?使用一名助手。时期。如果你知道只有一个线程在写,你可以使用多个连接,你的读取速度会更快,但买家要小心。我没有测试那么多。
这是一篇更详细的博客文章和一个示例应用程序。
Gray 和我实际上正在打包一个基于他的 Ormlite 的 ORM 工具,该工具与 Android 数据库实现原生配合,并遵循我在博客文章中描述的安全创建/调用结构。那应该很快就出来了。看一看。
与此同时,还有一篇后续博文:
还要检查前面提到的锁定示例的 2point0分叉: