问题描述
我有一个从 API 获取数据的应用程序。所以基本上,现在,该应用程序是这样工作的:
我在网上做了一些关于如何实施高效的离线存储策略的研究,Google 建议使用工作管理器对请求进行排队,然后在连接时发送。
我实际上想知道如何实现这一点? (不是代码而是逻辑,即我应该每天安排对 API 的请求还是每次它连接到互联网时?)
如果有离线应用经验的人可以提供帮助,那就太好了。
我的网络请求是通过 Retrofit 完成的,我已经创建了一个执行 API 调用的类。
解决方法
请记住,WM(工作管理器)旨在在满足某些条件时执行操作(例如:用户有足够的电池、显示屏关闭等)。因此,这最终可能会导致您的数据在您需要时没有更新。 WM 适用于您希望发生的操作,但对于“立即”发生并不重要。我会说始终使用 Room DB 作为唯一的事实来源。如果数据在房间里,就显示它,如果没有,就取它,如果你不能,那么,你试过了。向用户发送消息。您可以使用 NetworkConnectivityListener
来监控连接并检查您是否有待处理的查询(您可以将此查询的参数存储在 Room 数据库中的另一个表中以方便使用)。因此,您需要查询数据库,获取待处理的查询(如果有)并执行它们,更新数据,然后让 ViewModel/Repository 决定是否有上下文来显示此数据 (UI)。
我觉得你已经很接近实现你所需要的了。
换句话说:
UI:观察其 viewModel 的某个 sealed class xxx
状态以告诉它做什么(显示空列表、显示错误、将数据传递给 recyclerview 适配器等)。
ViewModel:使用其 viewModelScope.launch { ... }
将调用 repository.fetch(...)
或类似的。当 Fragment 告诉它这样做时(例如用户按下按钮)或某个生命周期事件(例如 onStart),您的 viewModel 将获取这些数据。
在这种情况下,Repository 通常公开一个 flow
(如果您可以使用实验性 api)或一个可以执行以下操作的挂起函数(可能会因您的业务规则而异)
- 如果数据在数据库中可用,立即返回。
- 如果数据是旧的(或者我们仍然想刷新它),那么执行网络 API(如果有连接的话)。如果没有连接,您可以将此“待处理”查询存储在数据库中以备后用。您还可以在执行任何操作之前检查您是否有待处理的查询,可能它已经过时,或者您可能需要执行它。
- 无论如何,一旦查询通过,您就将结果插入到数据库中,并调用您在第 1 步中使用的相同方法。
- 如果您有查询(或使用此查询),请不要忘记更新您的“待处理”查询。
使用 WorkManager,您可以安排“从 API 获取数据”部分在某个时间发生(这样您的数据将保持更新),但我完全取决于您拥有的用例。
>