Android:如何锁定可通过ContentProvider访问的SQLite数据库(或执行原子条件操作的其他方式)

瓦西里

我在SQLite数据库中有两个表:entitiesuser_actions他们的近似方案:

在此处输入图片说明

程序的流程如下(ContentProvider处理的所有数据库访问):

  1. 用户执行一些修改实体之一的动作
  2. 相应的实体将entities立即更新locally_modified此实体的值设置为1
  3. 有关用户操作的信息存储在 user_actions
  4. 在将来的某个时候,将启动与服务器的同步会话(我使用SyncAdapter框架)
  5. 用户的操作从user_actions一步一个地上传到服务器,并在后台线程中从数据库中删除
  6. 当上传完成后,我需要明确locally_modified的标志entities

在这一点上,我遇到了我的原子性问题:与服务器的同步发生在后台线程中,因此用户可以使用该应用程序并执行其他操作。因此,在清除locally_modified实体的标志之前,我必须检查user_actions与该实体相对应的记录对于locally_modified设置为的每个实体,必须自动执行这三个步骤1

  1. 查询user_actions对应于实体的条目_id
  2. 测试来自#1的查询是否返回空集
  3. 清除locally_modified该实体以0

在上述情况下,我有三个问题:

Q1:有没有一种方法可以锁定通过Android中的ContentProvider访问的SQLite DB,使其只能由锁定线程访问?

Q2:如果对Q1的回答是肯定的,那么如果其他某个线程试图访问锁定的DB,会发生什么?我应采取哪些预防措施以确保可靠运行?

问题3:可以使用ContentProviderOperation使用条件逻辑执行原子事务吗?您可以使用此答案此博客文章中所述的“反向引用”来引用先前操作的结果,但是是否可以在某种if-else陈述中使用该结果呢?

谢谢

瓦西里

答案很简单,但这是一种“ hack”-只需添加Uri即可ContentProvider

例如:最初我ContentProvider支持以下URI:

  • Uri.withAppendedPath(MyContract.CONTENT_URI, "entities")
  • Uri.withAppendedPath(MyContract.CONTENT_URI, "user_actions")

为了支持问题中描述的原子操作,我添加了一个额外的功能Uri

  • Uri.withAppendedPath(MyContract.CONTENT_URI, "clear_modified_flag")

通过以下Uri方式更新时:

getContentResolver().update(
    MyContract.ClearModifiedFlag.CONTENT_URI,
    new ContentValues(),
    null,
    null);

ContentProvider执行一个SQLite transaction,该操作将在操作期间锁定数据库,并在发生任何错误的情况下回滚该数据库(如本答案所述)。

而已。

PS myContentProvider不会导出(即其他应用程序无法访问和使用它),因此可以安全地将Uri添加到其中。但是请记住,如果确实导出了ContentProvider,则暴露这样的功能可能会出现问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档