WorkManager 如何安排对 REST API 的 GET 请求?
How does WorkManager schedule GET requests to REST API?
我已经查看了 WorkManager 的代码实验室以及此处的一些示例,但我看到的代码中的所有内容要么与在设备上本地工作有关,要么与上传到服务器的工作有关,而不是下载数据和响应接收到的数据。在开发人员指南中它甚至说,"For example, an app might need to download new resources from the network from time to time," 所以我认为它非常适合这项任务。我的问题是 WorkManager 是否可以处理以下情况,如果不能,处理它的正确工具是什么:
- 安排一个每天在后台运行一次的作业
- 工作是从 REST API 获取数据(如果可能,post 将其提取到 LiveData 对象)。
- 当数据returns时,检查是否比本地数据新
- 通知用户新数据可用。
我的工人 class 看起来像这样:
public class MyWorker extends Worker {
@NonNull
@Override
public WorkerResult doWork() {
lookForNewData();
return WorkerResult.SUCCESS;
}
public void lookForNewData() {
MutableLiveData<MyObject> liveData = new MutableLiveData<>();
liveData.observe(lifeCycleOwner, results -> {
notifyOnNewData(results);
})
APILayer.getInstance().fetchData(searchParams, liveData)
}
我的问题当然是LiveData对象无法观察,因为没有activity或fragment可以作为它的LifecycleOwner。但是,即使我使用来自 API 的回调来响应到达的数据,我的工作人员也应该已经 post 确认它是成功的并且它可能不会继续回调,对吗?所以我知道这种方法是完全错误的,但我看不到任何使用 WorkManager
获取数据的代码
请提供适当的解决方案和一些示例代码或一些链接,如果 WorkManager 可以处理此类工作,或者其他更合适的东西,请提供帮助。
这是最初的想法。如果我错了,请有人纠正我。
my worker would already have posted that it was successful and it probably would not proceed with the callback, right?
我们可以使用来自 API 响应的回调,构建 worker 的输出数据并使用 worker.setOutputData()
设置它
然后收听来自 workManager 的 LiveData<WorkStatus>
。从这个工作状态我们可以使用 workStatus.getOutputdata()
获得输出数据。此数据可以为我们提供我们想要的 API 响应。
我们可以将此响应传递给工作链中的下一个工作人员,以执行更新本地数据库等任务。
- Schedule a job that runs once a day in background
您可以为此安排 PeriodicWorkRequest
,它应该与 enqueueUniquePeriodicWork
一起排队。这确保同一时间只能有一个 PeriodicWorkRequest
的特定名称处于活动状态。
Constraints constraint = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(MyWorker.class, 1, TimeUnit.DAYS)
.setConstraints(constraint)
.build();
WorkManager workManager = WorkManager.getInstance();
workManager.enqueueUniquePeriodicWork("my_unique_worker", ExistingPeriodicWorkPolicy.KEEP, workRequest);
- The job is to do a data fetch from the REST API (and post it to a LiveData object if possible).
这可以通过在您的工作人员 doWork()
内同步发送您的请求来完成。我不会在你的 Worker
class 中使用 LiveData
。我们稍后再谈。 API 调用在 Retrofit 中看起来像这样:
@Override
public WorkerResult doWork() {
Call<MyData> call = APILayer.getInstance().fetchData();
Response<MyData> response = call.execute();
if (response.code() == 200) {
MyData data = response.body();
// ...
} else {
return Result.RETRY;
}
// ...
return Result.SUCCESS;
}
- When the data returns, check that it is newer than local data.
您以同步方式获取了 API 数据。同步获取您的本地数据,并做任何您需要做的事情来比较它们。
- Notify the user that new data is available.
如果您使用 WorkManager
安排任务,则保证 运行,即使您的应用程序被强制退出或设备已重启。因此,您的任务可能会在您的应用未 运行ning 时完成。如果您想在任何情况下通知用户,您都可以发送通知。如果您想在某个屏幕内通知用户,您可以订阅您的任务状态。例如像这样(取自official guide):
WorkManager.getInstance().getStatusById(compressionWork.getId())
.observe(lifecycleOwner, workStatus -> {
// Do something with the status
if (workStatus != null && workStatus.getState().isFinished()) {
// ...
}
});
我们的例子还有 getStatusesForUniqueWork(String uniqueWorkName)
。
官方指南还解释了如何从您的任务中 return 数据,您可以使用它在您的 MutableLiveData
上调用 setValue()
。
我建议在您的 Worker
中更新您的本地数据,订阅您的工作人员状态,一旦成功更新您的 UI 使用本地数据(如果您没有订阅您的本地数据,即 Room 和 LiveData
)。
编辑: 关于第 4 点,定期工作请求的读取状态有点不同。他们只在 ENQUEUED
和 RUNNING
之间切换,直到 CANCELLED
。但永远不会有 SUCCEEDED
或 FAILED
状态。因此,监听 isFinished()
可能不是您所期望的。
我已经查看了 WorkManager 的代码实验室以及此处的一些示例,但我看到的代码中的所有内容要么与在设备上本地工作有关,要么与上传到服务器的工作有关,而不是下载数据和响应接收到的数据。在开发人员指南中它甚至说,"For example, an app might need to download new resources from the network from time to time," 所以我认为它非常适合这项任务。我的问题是 WorkManager 是否可以处理以下情况,如果不能,处理它的正确工具是什么:
- 安排一个每天在后台运行一次的作业
- 工作是从 REST API 获取数据(如果可能,post 将其提取到 LiveData 对象)。
- 当数据returns时,检查是否比本地数据新
- 通知用户新数据可用。
我的工人 class 看起来像这样:
public class MyWorker extends Worker {
@NonNull
@Override
public WorkerResult doWork() {
lookForNewData();
return WorkerResult.SUCCESS;
}
public void lookForNewData() {
MutableLiveData<MyObject> liveData = new MutableLiveData<>();
liveData.observe(lifeCycleOwner, results -> {
notifyOnNewData(results);
})
APILayer.getInstance().fetchData(searchParams, liveData)
}
我的问题当然是LiveData对象无法观察,因为没有activity或fragment可以作为它的LifecycleOwner。但是,即使我使用来自 API 的回调来响应到达的数据,我的工作人员也应该已经 post 确认它是成功的并且它可能不会继续回调,对吗?所以我知道这种方法是完全错误的,但我看不到任何使用 WorkManager
获取数据的代码请提供适当的解决方案和一些示例代码或一些链接,如果 WorkManager 可以处理此类工作,或者其他更合适的东西,请提供帮助。
这是最初的想法。如果我错了,请有人纠正我。
my worker would already have posted that it was successful and it probably would not proceed with the callback, right?
我们可以使用来自 API 响应的回调,构建 worker 的输出数据并使用 worker.setOutputData()
设置它
然后收听来自 workManager 的 LiveData<WorkStatus>
。从这个工作状态我们可以使用 workStatus.getOutputdata()
获得输出数据。此数据可以为我们提供我们想要的 API 响应。
我们可以将此响应传递给工作链中的下一个工作人员,以执行更新本地数据库等任务。
- Schedule a job that runs once a day in background
您可以为此安排 PeriodicWorkRequest
,它应该与 enqueueUniquePeriodicWork
一起排队。这确保同一时间只能有一个 PeriodicWorkRequest
的特定名称处于活动状态。
Constraints constraint = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(MyWorker.class, 1, TimeUnit.DAYS)
.setConstraints(constraint)
.build();
WorkManager workManager = WorkManager.getInstance();
workManager.enqueueUniquePeriodicWork("my_unique_worker", ExistingPeriodicWorkPolicy.KEEP, workRequest);
- The job is to do a data fetch from the REST API (and post it to a LiveData object if possible).
这可以通过在您的工作人员 doWork()
内同步发送您的请求来完成。我不会在你的 Worker
class 中使用 LiveData
。我们稍后再谈。 API 调用在 Retrofit 中看起来像这样:
@Override
public WorkerResult doWork() {
Call<MyData> call = APILayer.getInstance().fetchData();
Response<MyData> response = call.execute();
if (response.code() == 200) {
MyData data = response.body();
// ...
} else {
return Result.RETRY;
}
// ...
return Result.SUCCESS;
}
- When the data returns, check that it is newer than local data.
您以同步方式获取了 API 数据。同步获取您的本地数据,并做任何您需要做的事情来比较它们。
- Notify the user that new data is available.
如果您使用 WorkManager
安排任务,则保证 运行,即使您的应用程序被强制退出或设备已重启。因此,您的任务可能会在您的应用未 运行ning 时完成。如果您想在任何情况下通知用户,您都可以发送通知。如果您想在某个屏幕内通知用户,您可以订阅您的任务状态。例如像这样(取自official guide):
WorkManager.getInstance().getStatusById(compressionWork.getId())
.observe(lifecycleOwner, workStatus -> {
// Do something with the status
if (workStatus != null && workStatus.getState().isFinished()) {
// ...
}
});
我们的例子还有 getStatusesForUniqueWork(String uniqueWorkName)
。
官方指南还解释了如何从您的任务中 return 数据,您可以使用它在您的 MutableLiveData
上调用 setValue()
。
我建议在您的 Worker
中更新您的本地数据,订阅您的工作人员状态,一旦成功更新您的 UI 使用本地数据(如果您没有订阅您的本地数据,即 Room 和 LiveData
)。
编辑: 关于第 4 点,定期工作请求的读取状态有点不同。他们只在 ENQUEUED
和 RUNNING
之间切换,直到 CANCELLED
。但永远不会有 SUCCEEDED
或 FAILED
状态。因此,监听 isFinished()
可能不是您所期望的。