异步Android SQLite数据库的正确实现

Posted

技术标签:

【中文标题】异步Android SQLite数据库的正确实现【英文标题】:Correct implementation of asynchronous Android SQLite database 【发布时间】:2016-03-23 08:59:36 【问题描述】:

我搜索了一下,发现了多种异步访问本地 SQLite 数据库的方法:

异步任务 CursorLoader(我已经使用它进行查询以检索我的联系人信息,但我不确定这将如何转换为具有多个查询的 SQLiteOpenHelper 子类) ContentProvider - 不确定它是否过度,数据库将只需要在应用程序内

最佳做法是什么?我目前有一个 SQLiteOpenHelper 子类,其中包含基本的表创建/升级/等。逻辑。

【问题讨论】:

你是在说只读操作(查询),还是写操作(插入、更新、删除)? 读写操作。 【参考方案1】:

CursorLoader 仅支持查询。如果您在 UI 中显示数据,您可能仍想使用它并利用 Loader 框架。 CursorLoader 旨在与 ContentProvider 一起使用,但您可以复制源代码并对其进行修改以采用 SQLiteDatabase 而不是 Context 并在 loadInBackground() 方法内查询数据库而不是 ContentResolver

对于写操作,您有几个选项需要考虑(这些选项并不相互排斥,您最终可能会根据情况使用多个选项):

异步任务 处理程序 意图服务 异步查询处理程序 Java 线程/执行器框架

我通常将AsyncTask 用于可能对 UI 产生轻微影响的一次性操作(例如,在屏幕上显示和隐藏某些指示器)。请注意,AsyncTasks 在单个工作线程上串行运行,除非您将自己的 Executor 提供给 execute()

IntentService 很有用,因为它将所有启动命令排队并在工作线程上串行执行,并在完成所有命令后自动关闭。它是一项服务,因此它与任何活动/UI 组件分开运行,但这也意味着存在一些开销,因为它是一个需要由系统创建和启动的应用程序组件。我喜欢它们用于批处理操作或将来某个时间安排的操作。

AsyncQueryHandler 不仅仅是查询(尽管它是如何命名的),但就像CursorLoader 它希望您与ContentProvider 通信。您可以使用一个来处理不同类型的操作。需要注意的是,ContentProvider 本身不提供异步处理,您必须从后台线程调用它,这正是 AsyncQueryHandler 所做的。

最后,良好的旧 Java 线程和执行器框架工作得很好,尽管您可能希望有某种应用程序组件供它们运行(可能是服务,但如果是这种情况,您可能会选择IntentService 无论如何都在上面)。

【讨论】:

感谢您的回复,我发现它非常有帮助。但是,仍然有一些事情困扰着我:AsyncQueryHandler 似乎无法进行批量插入。这对我来说有点问题,因为我想在数据库中插入几百条记录。在那种情况下,getContentResolver().applyBatch 会更适合这项工作吗? (我假设这将在 UI 线程上运行)。还是我应该通过 AsyncQueryHandler 调用 startInsert 几百次?看起来 IntentService 子类毕竟不是一个坏主意......【参考方案2】: CursorLoader 仅用于异步读取数据 ContentProvider 是为其他应用提供数据,没有同步或异步访问的选项。

我建议你使用AsyncTask

【讨论】:

这是不正确的。 ContentProvider 也可以为您自己的应用程序提供数据。 @Karakuri 请阅读文档:developer.android.com/reference/android/content/…“仅当您需要在多个应用程序之间共享数据时才需要内容提供程序。” 我已经构建了至少六个使用 ContentProvider 的应用程序,其中大多数不与其他应用程序共享数据。不需要它并不意味着你不能使用它。

以上是关于异步Android SQLite数据库的正确实现的主要内容,如果未能解决你的问题,请参考以下文章

ANDROID_MARS学习笔记_S04_002_用AsyncTask实现异步操作

android sqlite3命令行检查自己的代码操作数据库是否正确

Android 应用程序以异步方式将数据同步到远程服务器

Android clear listview 链接到 SQLite

Android SQLite用户登录不起作用

在android中链接2个异步任务的正确方法