在 Android ContentProvider 中从网络同步时防止网络同步循环
我正在编写自己的 ContentProvider,它将使用 SyncAdapter 同步到 Web 服务。
当同步适配器修改内容提供程序的数据时,会发生问题;当内部调用 getContentResolver().notifyChange 导致同步循环时,提供程序会触发网络同步。
当客户端应用程序进行修改时,需要使用带有网络同步标志的notifyChange,但在同步适配器正在修改时应避免使用。
在内容提供者内部,如何轻松判断它是由客户端应用程序(在修改时应触发网络同步)还是由同步适配器(不应触发网络同步)使用。
目前,我正在使用不同的 CONTENT_URI(同步适配器使用 CONTENT_URI_NO_SYNC 访问数据,客户端应用程序使用 CONTENT_URI),以便能够区分两种类型的访问并相应地设置网络同步标志。
I'm writing my own ContentProvider which will be synced to a web service using a SyncAdapter.
Problem happens when the sync adapter is modifying the content provider's data the provider triggers a network sync when internally calling getContentResolver().notifyChange causing a sync loop.
The notifyChange with the network sync flag is required for when a client application does the modification but should be avoided when the sync adapter is modifying.
How can one, inside a contentprovider, easly tell if it's being used by a client application (which should trigger network sync upon modification) or by a sync adapter (which should not trigger network sync).
Currently I'm using different CONTENT_URI's (sync adapter accesses the data using a CONTENT_URI_NO_SYNC and client apps using a CONTENT_URI) to be able to distinguish between the two types of access and set the network sync flag accordingly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
观看此视频,了解
SyncAdapter
中的 REST API 使用情况。他们讨论的方法是将一组元数据标志列添加到数据库中。这让我们可以做三件事。
标志本身允许 SyncAdapter 确定需要更改的行以及这些更改是什么。如何区分本地创建的行和本地修改的行?此外,您如何知道要进行哪个 REST API 调用?如果您只是删除一行,那么如果数据现在消失了,您的
SyncAdapter
如何知道要删除的行?相反,设置“应删除”标志,然后,当SyncAdapter
运行时,它知道将删除推送到服务器。这些标志允许您的
CursorAdapter
修改创建的视图(例如添加Spinner
来显示“此行正在同步”)最后,它们不要指出,这些标志可以让您了解该行被修改的原因。如果没有设置任何标志并且行发生更改,则一定是由于服务器的更新所致。因此,无需同步到网络。
因此,两个工作流程如下:
本地更改
notifyChange(...,true);
SyncAdapter
触发。SyncAdapter
清除标志。(ContentProvivder
上的行更新)ContentProvider
看到标志已清除,没有设置任何标志,因此它调用通知更改(...,假);所有这些步骤对于更新/删除来说是等效的——每个创建/更新/删除的每个可同步行一个标志。
还要注意另一个胜利——如果“创建”暂时失败怎么办?服务器宕机...你怎么知道要重试? -- 很简单,您没有清除“创建”标志,15 分钟后您就会看到它。
远程更改
SyncAdapter
由于定期同步而触发。SyncAdapter
从服务器获取更新。将更改推送到数据库中。不设置任何标志。ContentProvider
发现缺少标志,知道更改必须来自服务器(或者不是需要推送到服务器的数据库更改),因此它调用notifyChange(. ..,false);
ContentObserver
看到内容更改,因此它们使用新的行数据进行更新Watch this video about REST API usage in
SyncAdapter
s.The method they discuss is to add a set of metadata flags columns to the database. This allows us to do 3 things.
The flags themselves allow the
SyncAdapter
to determine the rows that need changes and what those changes are. How do you tell the difference between a locally created row and a locally modified row? Furthermore how do you know which REST API call to make? If you just delete a row, how does yourSyncAdapter
know the row to be deleted if the data is now gone? Instead, set the "Should be deleted" flag, and then, when theSyncAdapter
runs, it knows to push a delete to the server.The flags allow your
CursorAdapter
to modify the view that is created (like adding aSpinner
to show that "This row is being synced")Finally, and this they don't point out, the flags allow you to tell why the row is being modified. If none of the flags are set and the row changes, it must have been because of an update from the server. Therefore, no need to sync to network.
So, the two workflows are as follows:
Local change
notifyChange(...,true);
SyncAdapter
to fire.SyncAdapter
scans the database, finds the row with create flag set and performs appropriate server action. After success,SyncAdapter
clears the flag.(row update onContentProvivder
)ContentProvider
sees the flag clear, no flags are left set, so it calls notifyChange(...,false);ContentObserver
s see the flag change, update to look like "sync finished"All these steps are equivalent for update / delete -- one flag per syncable row for each of create/update/delete.
Also notice the other win -- what if "Create" fails temporarily? server down... How do you know to retry? -- Simple, you don't clear the "Create" flag and you see it 15 minutes later.
Remote Change
SyncAdapter
fires due to periodic sync.SyncAdapter
fetches an update from the server. Pushes changes into the database. Doesn't set any flags.ContentProvider
sees the lack of flags, knows the change must have come from the server (or isn't a database change that needs to be pushed to the server), so it callsnotifyChange(...,false);
ContentObserver
s see the content change and so they update with new row data