WorkManager如何安排对REST API的GET请求? [英] How does WorkManager schedule GET requests to REST API?

查看:57
本文介绍了WorkManager如何安排对REST API的GET请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看过WorkManager的代码实验室以及此处的一些示例,但是我看到的代码中的所有内容都与在设备上本地执行工作或上载到服务器上工作有关,而不是下载数据并响应收到的数据.在开发人员指南中,它甚至说:例如,一个应用可能需要不时从网络下载新资源,"因此我认为这对于完成这项任务将是完美的.我的问题是,WorkManager是否可以处理以下情况,否则,什么是处理该问题的适当工具:

I've had a look at the codelab for WorkManager plus some examples on here, but everything in code I have seen is either related to doing work locally on the device or work uploading to the server, not downloading data and responding to the data received. In the developer guidelines it even says, "For example, an app might need to download new resources from the network from time to time," so I thought it would be perfect for this task. My question is if WorkManager can handle the following scenario and if not, what is the proper tool for handling it:

  1. 安排每天在后台运行一次的作业
  2. 工作是从REST API提取数据(如果可能,将其发布到LiveData对象).
  3. 返回数据后,检查它是否比本地数据新.
  4. 通知用户新数据可用.

我的工人阶级看起来像这样:

My worker class looks something like this:

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对象无法观察到,因为没有活动或片段可以成为其LifecycleOwner.但是,即使我使用来自API的回调来响应到达的数据,我的工作人员也已经发布了该消息是成功的,并且可能不会继续进行回调,对吗?所以我知道这种方法是完全错误的,但是我看不到任何使用WorkManager获取数据的代码

My issue is of course that the LiveData object can't observe because there is no activity or fragment that can be its LifecycleOwner. But even if I used a callback from the API to respond to the data arriving, my worker would already have posted that it was successful and it probably would not proceed with the callback, right? So I kind of know this approach is totally wrong, but I can't see any code for getting data with WorkManager

请提供适当的解决方案和一些示例代码或某些链接的帮助,如果可以处理此类工作,请使用WorkManager,如果更合适,请使用其他方法.

Please help with a proper solution and some example code or some links, either with WorkManager if it can handle this kind of work or something else if it is more appropriate.

推荐答案

  1. 安排每天在后台运行一次的作业

您可以为此安排一个 PeriodicWorkRequest ,该请求应与 enqueueUniquePeriodicWork 排队.这样可以确保一次只能使用一个具有特定名称的 PeriodicWorkRequest .

You can schedule a PeriodicWorkRequest for that, which should be queued with enqueueUniquePeriodicWork. This makes sure only one PeriodicWorkRequest of a particular name can be active at a time.

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);

  1. 工作是从REST API提取数据(如果可能,将其发布到LiveData对象).

这可以通过在工作人员的 doWork()中同步发送您的请求来完成.我不会在您的 Worker 类中使用 LiveData .我们稍后再说.例如,使用Retrofit可以看到API调用,例如:

This can by done by sending your request synchronously within doWork() of your worker. I wouldn't use LiveData within your Worker class. We come to that later. The API call would look with Retrofit for example like that:

@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;
}

  1. 返回数据后,检查它是否比本地数据新.

您以同步方式获取了API数据.还可以同步获取本地数据,并执行所需的操作以比较它们.

You fetched your API data in a synchronous way. Fetch your local data also synchronously and do whatever you need to do to compare them.

  1. 通知用户新数据可用.

如果使用 WorkManager 安排任务,则即使您的应用已强制退出或设备已重启,也可以保证运行任务.因此,当您的应用未运行时,您的任务可能会完成.如果您想在任何情况下通知用户,则可以发送通知.如果要在特定屏幕上通知用户,则可以订阅您的任务状态.例如(从官方指南摘录):

If you schedule a task with WorkManager it is guaranteed to run, even if your app is force-quit or the device is rebooted. So your task might complete while your app is not running. If you want to notify the user in any case you can send a notification. If you want to notify the user within a certain screen you can subscribe on your tasks status. For example like this (taken from the official guide):

WorkManager.getInstance().getStatusById(compressionWork.getId())
.observe(lifecycleOwner, workStatus -> {
    // Do something with the status
    if (workStatus != null && workStatus.getState().isFinished()) {
        // ...
    }
});

在我们的示例中,还有 getStatusesForUniqueWork(String uniqueWorkName).

There's also getStatusesForUniqueWork(String uniqueWorkName) for our example.

官方指南还说明了如何从您的任务中返回数据,例如,您可以使用该任务在 MutableLiveData 上调用 setValue().

The official guide is also explaining how to return data from you Task with which you can call setValue() on your MutableLiveData for example.

我建议在您的 Worker 中更新您的本地数据,订阅您的工作人员状态,然后成功使用本地数据更新您的UI(如果您始终未订阅本地数据,即使用Room和 LiveData ).

I would propose to update your local data within your Worker, subscribe on your workers status and once it succeeds update your UI with the local data (if you are not subscribed on your local data anyways, i.e. with Room and LiveData).

编辑:关于第4点,定期工作请求的阅读状态略有不同.它们仅在 ENQUEUED RUNNING 之间切换,直到 CANCELLED .但是永远不会具有状态 SUCCEEDED FAILED .因此,收听 isFinished()可能不是您所期望的.

In reference to point 4, reading status of periodic work requests works a little different. They are only switching between ENQUEUED and RUNNING until CANCELLED. But will never have the state SUCCEEDED or FAILED. So listening for isFinished() might not be what you are expecting.

这篇关于WorkManager如何安排对REST API的GET请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆