我正在尝试在我的应用程序中使用与WebService同步的事件进行自定义日历。
一切都很顺利(嗯,不太好)。
Calendar活动启动一个AsyncTask,以获取当前的月份事件并将其存储在数据库中,onPostExecute方法将更新视图以每天正确标记。
当用户进入日历活动,然后快速返回到主活动几次时,我的问题就出现了,比如说
Main Activity > Calendar Activity (按后退按钮)> Main Activity > Calendar Activity (按后退按钮)>
此时,活动因database lock has not been available for 30 sec.或应用程序崩溃而冻结,原因是SQLiteConstraintException: error code 19崩溃
编辑:
SQLiteConstraintException行为不再发生
因为在我的应用程序中,更新是非常重要的,所以每次我重新输入日历活动时,我都会删除数据库并用服务器新数据重新填充它--即使很难--它也是一样的,此时正是锁的位置。
编辑: 我已将
Delete > Insert样式更改为:Updateall data (setflag列= 0) >Insertnew data (setflag列= 1) >Delete(其中flag列= 0)
我已经尝试过this解决方案来取消活动结束时的AsyncTask,但没有成功。
我确信问题是我没有完全理解,理解我所做的事情的过程,所以我遗漏了一些非常重要的东西(或基本的)。
任何帮助改进我的代码或只是指向正确的方向,将不胜感激。
提前感谢!
编辑: 我的应用程序有一个
Aplication,它负责创建单个数据库连接(getWriteableDatabase();),这种独特的连接可以通过MyApp.getDatabase();方法访问。
发布于 2012-11-20 16:24:01
主活动>日历活动(按后退按钮)>主活动>日历活动(按后退按钮)>
这可能会在每次打开日历时创建和启动一个新的AsyncTask。
如果不取消每个AsyncTask,那么它仍然会运行。
如果AsyncTask并行或序列化运行,则取决于用于执行它们的Android / executor。>=蜂窝的默认行为是串行执行。在 documentation中的执行顺序部分中解释。
如果使用串行AsyncTask,您可以将几个(旧的)任务排队起来,并且可能需要相当长的时间才能执行最新的任务。当您离开某个活动时,取消任务可能是个好主意。
您得到的database lock has not been available for 30 sec.警告指示您在一个线程中写入,同时尝试从另一个线程访问数据库。不确定这是否需要两个并行的写线程。
问题不是使用不同的SQLiteDatabase实例。如果你这么做,我想你会得到错误而不是警告,因为安卓不能检查某个随机的SQLiteDatabase对象是否对数据库有写锁。
那么,您能做什么:我假设您使用事务,因为在没有事务的情况下锁定数据库很长时间是不可能的。
db.yieldIfContendedSafely()动态停止事务。这将检查另一个线程是否希望访问数据库并暂时结束事务。缺点:它将提交更改,您不能回滚整个事务。SQLiteDatabase#enableWriteAheadLogging()和beginTransactionNonExclusive()进行实验。它似乎可以允许多线程访问,而不会出现锁定问题。我还没有进一步调查这是否有效,以及它有什么副作用。发布于 2012-11-19 18:14:15
尝试序列化对数据库的访问。SQLiteDatabase的每个实例表示指向SQLite DB的单独链接。在单个SQLiteDatabase实例上执行的操作是序列化的,但是当您在多个线程中处理多个SQLiteDatabase实例时,您所描述的but开始弹出。
您没有发布任何代码,所以我假设您每次访问数据库时都会得到一个新的SQLiteDatabase实例(带有.getWriteableDatabase() / .getReadableDatabase())。尝试使用单个SQLiteDatabase实例并将其传递给任务。这样,您将序列化db访问,并避免AsyncTask线程争用DB锁。
https://stackoverflow.com/questions/13458201
复制相似问题