移动应用数据管理

9
我的问题围绕一个单一的点——移动应用中的数据管理。我创建了一个移动应用程序,其中数据来自服务器,并包括文本和图像。以下是我为此所做的步骤:

首次启动:
1. 获取服务器数据。
2. 将服务器数据保存在Sqlite数据库中。
3. 显示Sqlite数据。

后续启动:
1. 显示Sqlite数据。
2. 后台获取服务器数据。
3. 删除之前的Sqlite数据。
4. 将新的服务器数据保存在Sqlite数据库中。
5. 显示Sqlite数据。

关于这些步骤,我有几个问题:
1. 这是正确的方法吗?另一种方法是每次都从服务器显示数据,但这不会立即在屏幕上显示数据(取决于互联网速度)。
2. 我还考虑过将Sqlite数据与新的服务器数据进行比较。但面临一个巨大的挑战。新的服务器数据可能具有新记录或已删除记录。而且,我无法找到适当的方法来将每个数据库字段与JSON数据进行比较。
那么在比较本地Sqlite数据和新的服务器数据方面,哪种是最好的方法?
3. 每次我删除Sqlite数据并插入新数据,然后刷新屏幕(其中包含一个UITableView),它会闪烁一秒钟,这是很明显的。 如果按照步骤3、4、5进行,如何避免此问题?
4. 如果每次回到屏幕或应用程序再次变为活动状态,我该如何处理数据更新?我非常清楚可以使用NSOperationQueues或使用GCD来处理。但如果我反复在屏幕之间来回移动怎么办?会有很多NSOperations在队列中。

在您的方法中,如果服务器数据不包含新数据/服务器发生了变化。那么针对这种情况,您会在后台下载服务器数据吗? - Jamil
@jamil65able:是的,没错。 - Nitish
@Nitish 你是同时为服务器端和设备端编写代码吗? - vignesh kumar
听起来数据是只读的,用户从未修改它,也不需要将其推回服务器。这是正确的吗?如果是这样,那么工作会变得更容易。如果有什么东西可以被视为主键,那么它会更容易,但听起来你考虑每个数据都是唯一的?你有独特性的想法,还是总是想要从服务器获取所有数据。如果您可以避免在UI中替换数据,您可能可以避免闪烁。数据有排序吗?这将帮助我们回答。谢谢。 - rholmes
4个回答

2

这是一个好问题。

我个人认为,下载数据并在本地存储后再尝试同步是一种危险的情况。很容易引入错误,主从问题(如果要使用多个设备,则应该将哪些数据作为主数据等)。

我认为以下方法可能是可行的:

1. 我会尝试查看从服务器按需懒加载数据的可能性。也就是说,当用户有一个视图需要显示数据时,使用创建该特定视图时加载该特定数据。这确保了数据始终保持同步。

2. 解决从每个视图重新加载数据的需要可以通过简单地将下载的数据存储为内存中的对象(不使用SqlLite)来完成。视图将尝试通过缓存管理器加载所需数据,并且如果可用,它将从内存中提供数据。如果不在内存中,则从服务器获取数据并将其添加到内存缓存中。内存缓存可以是自制的数据管理器,包装在您的AppDelegate上存储的Dictionary上,或者是一些全局“Singelton”来包装缓存管理/存储和数据加载。

3. 使用懒加载数据和内存缓存,您需要确保任何更新(更改、新记录、删除记录)都会更新您的内存数据模型,并尽快将这些更改推送到服务器。根据数据大小等,您可以强制用户等待或直接作为后台进程进行。

4. 为确保数据同步,您应该确保定期使缓存中的本地内存记录无效(删除),从而强制从服务器更新数据。最好的方法可能是为内存缓存中的每个记录设置最后更新时间戳。因此,周期性的无效器仅会从内存缓存中删除“旧记录”(再次不从服务器中删除)。

为了避免服务器不必要的数据负载,数据仍应在用户需要在视图中使用时按需加载,而不是作为“缓存失效”的一部分。

5. 根据数据大小,您可能需要查看“缓存失效”。可能只需要在存储xx条记录时,开始从内存缓存中删除旧对象(仅在设备上本地删除,而不是服务器)。

6. 如果数据同步绝对关键,则可能需要在允许用户更改数据之前刷新其内存缓存中的记录。例如,当用户点击“编辑”或类似选项时,您可以为该记录从服务器获取最新数据。这只是为了确保用户不会使用过时的数据更新记录,并且因此意外覆盖远程或其他设备上进行的任何更改等。

--

这是我的看法。我不认为有一种“完美正确的方法”来解决这个问题。但这就是我会尝试做的。

希望这些想法和灵感能帮助到您。

enter image description here


2

同步服务器数据是一个挑战,如果你能花时间解决这个问题,我认为这是最好的解决方案。

可能需要在服务器和本地对象上记录创建和修改日期,以便比较它们,这将让您决定添加、更新和删除哪些对象。如果服务器只发送最近更新的对象,您可以节省大量流量并提高性能(但删除的对象将更难检测)。

如果数据只在服务器上更改,那么就比较容易处理;如果应用程序也可以更改数据,则变得更加复杂(但似乎不是您的情况)。当然,这还取决于数据库的复杂程度。

如果您不想花时间做这个,每次都获取全部数据也可以,即使不是最理想的情况!而不是显示旧数据并闪烁,您可以让用户在进入时等待2-3秒钟,同时获取新数据。或者,您可以仅在启动应用程序时获取数据,这样当您到达该视图控制器时,数据将已准备好。

这是一个复杂的问题,每个人在某个时候都会面临,所以我很想看看其他人会提出什么建议 :)


感谢您的想法。数据也可以从应用程序中更改。我拥有的本地数据库与复杂的服务器数据库不同。我根据屏幕上需要显示的内容创建表格。JSON具有许多我不需要的数据字段,这些字段我没有包含在表格中。等待2-3秒是一个好选择,但根据客户要求,数据应立即显示。 - Nitish
只需在JSON中选择所需的对象(比较修改日期),并将每个对象添加/更新到数据库中。如果JSON数据过多且接收/解析时间过长,则可能需要向服务器端人员请求一个更简单的Web服务 :) - Tiago Lira

1
你可以通过使用多版本并发控制(MVCC)更有效地完成同样的事情,它为每个数据记录使用一个计数器(一种非常简单的“时间戳”),每当记录更改时更新,这意味着您需要获取那些在最后同步调用之后更新的数据,从而减少了大量冗余数据和带宽。
来源:多版本并发控制

1
这样怎么样:
  1. 如果SqlLite中存在数据,则将其加载到“内存”副本中并显示
  2. 在后台加载新的服务器数据
  3. 如果存在旧的Sqlite数据,请删除它(请注意,内存副本仍然存在)
  4. 将新的服务器数据保存到Sqlite中
  5. 将新的Sqlite数据加载到“内存”副本中并显示

如果在第一步中没有找到数据,则在第2步期间向用户显示“加载”屏幕。

我假设SqlLite中的数据足够小,可以在内存中保留一份副本以在UITable视图中显示(UITable视图始终显示来自内存的数据)。

如果数据足够小,可能可以将步骤4和5组合在一起(完成后创建一个新的内存副本并与可见副本交换)。

注意: 我没有在这里讨论错误处理,但建议在有新数据替换它之前不要删除Sqlite数据。

此方法还消除了确定是否为第一次启动的需要。逻辑始终保持不变,这应该使实现变得更容易。

希望这对你有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接