【问题标题】:Android sqlite with multi thread具有多线程的Android sqlite
【发布时间】:2012-05-04 14:39:23
【问题描述】:

我正在使用sqlite 编写一个android 应用程序。有许多活动和一项服务。我从多个线程中使用数据库。它在Android 2.X 中完美运行,但是一旦我在Android 3.X 中运行它,它总是抛出这个错误和Force Close

05-04 22:17:04.815: I/SqliteDatabaseCpp(8774): sqlite returned: error code = 5, msg = database is locked, db=/data/data/xxx/databases/im
05-04 22:17:04.815: E/SqliteDatabaseCpp(8774): sqlite3_open_v2("/data/data/xxx/databases/im", &handle, 6, NULL) failed
05-04 22:17:04.835: E/SQLiteDatabase(8774): Failed to open the database. closing it.
05-04 22:17:04.835: E/SQLiteDatabase(8774): android.database.sqlite.SQLiteDatabaseLockedException: database is locked
05-04 22:17:04.835: E/SQLiteDatabase(8774):     at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
05-04 22:17:04.835: E/SQLiteDatabase(8774):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983)
05-04 22:17:04.835: E/SQLiteDatabase(8774):     at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956)
05-04 22:17:04.835: E/SQLiteDatabase(8774):     at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021)
05-04 22:17:04.835: E/SQLiteDatabase(8774):     at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:790)
05-04 22:17:04.835: E/SQLiteDatabase(8774):     at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
05-04 22:17:04.835: E/SQLiteDatabase(8774):     at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149)

有人知道为什么会发生以及如何解决吗?

我在互联网上进行了研究,大多数人建议:

  1. 仅为应用程序使用一个 DB 连接。如何保证?我想为服务和活动共享数据库连接。我应该通过创建一个公共静态数据库变量来做到这一点吗?
  2. ContentProvider - 我在代码中使用了复杂的 SQL 语句(例如连接几个表、临时表)。是否可以在 ContentProvider 中运行这些复杂的 SQL 语句?


    谢谢大家。最后,(1)对我来说很好。但是我还是想知道为什么Android 2.X没有这个问题。

【问题讨论】:

  • 1) 仅当所有访问都发生在同一个进程中时才有效,2) 只要​​您只需要插入/查询/更新/删除即可工作,但复杂的查询看起来很难看,因为您仅限于developer.android.com/reference/android/content/…接口
  • 感谢 zapl,数据库不与其他应用程序共享。我认为(1)对我有好处。你知道为什么 Android 2.X 没有这个问题吗?
  • @mobileappBeginner No :(
  • 谢谢阿南德,使用完数据库和光标我已经关闭了。但是还是报错

标签: android multithreading sqlite android-loadermanager


【解决方案1】:

1 号就是答案。我有几个关于如何做到这一点的堆栈答案和博客文章:

What are the best practices for SQLite on Android?

http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection

第 2 项是很多额外的工作,而且是不必要的。 ContentProvider 存在,因此您可以与其他应用程序共享数据。它用于管理数据库连接,因为人们不了解 Sqlite 和 Android 是如何协同工作的。

【讨论】:

  • 感谢 Kevin Galligan,我已阅读您的帖子。我在stackoverflow.com/questions/2493331/… 学到了很多东西。我正在尝试解决方案(1)。如果解决方案(1)失败,我将研究 ormlite。谢谢!
  • ORMLite 很好,但对于从多线程访问数据库来说完全没有必要。只需拥有一个静态 SQLiteOpenHelper 实例,或在 Application 实例中保留一个实例。如果您只有一个实例,您将永远不会遇到锁定的数据库问题。
  • 谢谢 Kevin,ORMLite 还是很棒的
【解决方案2】:

我建议您尽可能使用ContentProviderLoaderManager。它能够在后台自动执行查询。

【讨论】:

  • 感谢您的建议,但它需要许多额外的工作,并且数据库不会与其他应用程序共享。我认为解决方案(1)对我更好。如果(1)确实有效,我会考虑您建议的解决方案。谢谢
  • 我知道很多人喜欢 ContentProvider,但它对于多线程数据库访问完全没有必要。如果您只是为此使用它,则不需要它。但是,如果您喜欢 ContentProvider,请使用它。不过,这对我来说似乎是额外的工作。
猜你喜欢
  • 2017-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 1970-01-01
相关资源
最近更新 更多