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