如何在移动应用程序中处理过时的缓存记录

时间:2014-09-05 21:23:01

标签: android sqlite rest mobile synchronization

我正在创建一个使用REST API的Android应用程序(我的第一个)。 我使用后台作业来获取内容,我计划使用带有from_id参数的GET请求,以获得更多内容。当然,从API获取的任何东西都存储在SQLite数据库中(我使用的是greendao),而应用程序只使用已经存在的数据,以便更加快捷。

所以,问题是:如果在服务器上更新给定记录会发生什么?如果一旦读取的记录被缓存,应用程序将如何注意到有同步更改?哪种策略是可行的解决方案?

感谢。

编辑:

正如Satish P在他的回答中指出的那样,客户端 - 服务器通信是用ETag处理的(我必须添加使用If-Modified-Since的可能性。)

但我主要担心的是如何将其与应用UI混合使用。给出这个例子:

  1. 从本地数据库中读取已从REST服务检索但客户端的元素列表,以使应用程序更具响应性。
  2. 用户点击其中一个元素并显示详细视图。同样,数据从本地数据库加载。我想在这一点上要求使用ETag或If-Modified-Since标头来获取特定记录的GET请求。
  3. 服务器返回修改后的记录,因此修改了本地数据,所以现在是时候更新用户看到的内容了。
  4. 问题:如果已填充详细视图,因为远程请求返回时已完成本地数据库读取,如何更新视图?我不认为只用更新的数据替换当前数据是可以接受的,用户会看到一个突然的变化。

4 个答案:

答案 0 :(得分:4)

对于您需要服务器做什么,Satish的答案绝对正确。要点是它需要支持ETags和304响应代码,以防自上次从服务器获取内容后内容未发生变化。现在在客户端,你可以遵循三种策略(每种策略都有自己的优点和缺点):

  1. 如果内容未更改,则仅使用缓存。这意味着您将始终执行请求并向用户显示进度条。如果服务器返回304,那么您的内容没有更改,请求将非常快(当您看到它时,您将显示缓存的内容)。如果服务器实际返回新内容,则继续显示进度条,并在加载内容时显示新内容。这样做的好处是用户只能看到有效的内容,因此避免了您的许多麻烦。不好的是,应用程序看起来并不那么快(特别是如果内容发生了变化而你的连接速度很慢)。
  2. 在预定义的时间段内仅使用缓存,然后回退到第一种情况。有一些缓存标头用于定义该句点('max-age'和'Expires')。在此之前,您始终使用缓存(不执行请求),然后执行请求并查看内容是否已更改。关于这种方法的好处是,在上述时期内,应用程序非常快。不好的是,用户可能会查看不正确的内容。
  3. 在预定义的时间段内使用缓存和网络,然后回退到第一种情况。您可以以不同的方式使用前面提到的缓存头。您可以实际显示缓存的内容并在后台执行请求,而不是仅显示缓存的内容。如果该请求以304返回,那么您将不得不使用新数据更新UI(期望两个响应,一个包含缓存数据,另一个包含新检索到的数据)。这方面的积极因素是您可以获得快速体验和有效数据(大多数情况下)。否定的是,您为应用程序添加了很多复杂性(如果用户与陈旧数据交互,然后第二个响应进来等,会发生什么情况。)
  4. 总而言之,每个策略都有效,具体取决于用例。例如,如果用户无法与显示数据的屏幕(如电视节目)进行交互,则第三个选项非常好。如果用户看到正确的数据至关重要(比如金融应用程序),那么第一个选项是最好的。如果速度比拥有最新数据(游戏或其他东西)更重要,那么第二个选项是您的最佳选择。

答案 1 :(得分:2)

客户端执行缓存的效率完全取决于您从客户端访问的REST API获得多少支持。

使用ETag是一种行业标准,可以提高客户端的缓存效率,并使服务器更快地提供服务。简而言之,ETag是LIKE返回内容的MD5哈希值。有关ETag的更多信息,请访问:http://en.wikipedia.org/wiki/HTTP_ETag

如果它是像谷歌,Facebook等流行的API,它们本身就支持ETag。 请查看以下链接:

ETag用法最好在此解释:https://developers.facebook.com/docs/reference/ads-api/etags-reference

  • 当客户端对特定资源执行GET操作时,服务器在回复内容时应包含ETag。
  • 客户端应该针对缓存的数据存储该资源的ETag。
  • 每当客户端使用缓存信息时,它应使用ETag验证缓存。可以多种方式工作,具体取决于服务实现
    • 对资源进行通常的GET,并将ETag作为请求的一部分。如果内容没有改变,理想情况下服务将不返回任何数据,但会给出特定的代码,如(304 - Not Modified)。客户端知道缓存仍然有效并继续使用它
    • 对资源进行HEAD调用,返回ETag。它是标准HTTP规范的一部分。 http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html(参见9.4)。在这种情况下,客户端将验证ETag并决定是否进行GET呼叫。

上述说明中的资源样本如下所示

GET http://serverapi.com/employees/2312312312

答案 2 :(得分:0)

最近我一直在做的是使用GraphQL和Apollo。它会自动处理所有这些内容,非常棒。

答案 3 :(得分:-1)

Javascript可以相当优雅地处理屏幕更新,重写DOM中的特定元素 - 可选地应用CSS格式以引起注意UI中的更改 - 如果UI中的每个数据都有唯一的ID /容器ID或以其他方式成为JS的目标。

打败某些缓存的一种简单/方法是将查询字符串附加到所需的资源。例如,可以在testfile.csv?12345轻松访问名为testfile.csv的文件 - 下次要绕过缓存时,只需更新查询字符串,例如testfile.csv?23456。如果在您的上下文中手动更新查询字符串是非常困难的,那么通过PHP以适度的性能命中为代价会更加聪明:调用资源作为testfile.csv以使查询字符串在每次查询后自动更新资源被修改;获取更新版本而不是缓存版本。