我正在尝试使用与WebService的事件同步在我的应用中执行自定义日历。
一切都很顺利(好吧,不是真的)。
日历活动启动AsyncTask
以获取当前月份事件并将其存储在数据库中,onPostExecute
方法更新视图以正确标记每一天。
我的问题出现在用户进入日历活动然后快速返回主要活动几次时,比方说吧
Main Activity
> Calendar Activity
(按返回按钮)> Main Activity
> Calendar Activity
(按返回按钮)> ...
此时由于database lock has not been available for 30 sec.
导致SQLiteConstraintException: error code 19
或应用程序崩溃导致活动冻结{/ 1}}
编辑:
SQLiteConstraintException
行为不再发生
由于在我的应用中更新非常重要,每次我重新输入日历活动时,我都会删除数据库,并使用服务器新数据重新填充它,即使是相同的,也是如此,并且在这一点上是锁定的地方。
编辑:
我已将
Delete > Insert
样式更改为:Update
所有数据(设置flag
列= 0)>Insert
个新数据(设置flag
列= 1)>Delete
(其中flag
列= 0)
我已尝试this解决方案取消活动结束时AsyncTask
但未成功
我确定问题是我不完全了解我正在做的事情,所以我错过了一些非常重要的事情(或基本的)。
任何有助于改进我的代码或只是指向正确方向的帮助都会非常感激。
提前致谢!
修改:
我的应用程序有
Aplication
,负责创建单个数据库连接(getWriteableDatabase();
),并且可以通过MyApp.getDatabase();
方法访问此唯一连接。
答案 0 :(得分:1)
尝试序列化对数据库的访问。 SQLiteDatabase的每个实例都代表一个指向SQLite DB的单独链接。在单个SQLiteDatabase实例上执行的操作是序列化的,但是当您在多个线程中处理多个SQLiteDatabase实例时,会出现如您所述的错误。
你没有发布任何代码,所以我假设每次在AsyncTasks中访问数据库时都会得到一个新的SQLiteDatabase实例(带.getWriteableDatabase()/。getReadableDatabase())。尝试使用单个SQLiteDatabase实例并将其传递给任务。这样,您将序列化数据库访问并避免AsyncTask线程竞争数据库锁。
答案 1 :(得分:0)
主要活动>日历活动(按后退按钮)>主要活动>日历活动(按后退按钮)> ...
这可能会创造&每次打开日历时都会开始一个新的AsyncTask
。
如果你没有明确地取消它,每个AsyncTask
仍会运行。
如果它们并行或序列化运行,它取决于你用来执行AsyncTask
的Android版本/执行程序。 > = Honeycomb的默认行为是串行执行。在AsyncTask
documentation中的执行顺序部分进行了解释。
如果使用串行AsyncTask,您可以将几个(旧)任务排队等待,并且在执行最近的任务之前可能需要相当长的时间。离开活动时取消任务可能是个好主意。
您收到的database lock has not been available for 30 sec.
警告表示您在一个线程中写入并尝试同时从另一个线程访问数据库。不确定这是否需要并行两个写线程。
问题是没有使用不同的SQLiteDatabase
实例。如果您这样做,我认为您会收到错误而不是警告,因为Android无法检查某个随机SQLiteDatabase对象是否在数据库上有写锁定。
那你能做什么: 我假设您使用事务,因为长时间锁定数据库没有事务几乎是不可能的。
db.yieldIfContendedSafely()
动态停止交易。这将检查另一个线程是否想要访问数据库并暂时结束事务。缺点:它将提交更改,您无法回滚整个事务。SQLiteDatabase#enableWriteAheadLogging()
&正如预写日志记录文档中提到的beginTransactionNonExclusive()
。它看起来像是可以允许多线程访问而不会出现锁定问题。我没有进一步调查是否有效以及它有什么副作用。