WorkManager如何安排对REST API的GET请求?

时间:2018-06-08 13:09:36

标签: android android-workmanager

我已经看过WorkManager的codelab以及这里的一些示例,但是我所看到的代码中的所有内容都与在设备上本地工作或上传到服务器有关,而不是下载数据和响应收到的数据。在开发人员指南中,它甚至说,“例如,一个应用程序可能需要不时地从网络上下载新资源”,所以我认为这对于这项任务来说是完美的。我的问题是,如果WorkManager可以处理以下场景,如果没有,那么处理它的正确工具是什么:

  1. 安排每天在后台运行一次的作业
  2. 工作是从REST API进行数据提取(如果可能,将其发布到LiveData对象)。
  3. 当数据返回时,检查它是否比本地数据更新。
  4. 通知用户新数据可用。
  5. 我的工人类看起来像这样:

    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获取数据的代码

    请帮助一个正确的解决方案和一些示例代码或一些链接,如果它可以处理这种工作或其他更合适的话,可以使用WorkManager。

2 个答案:

答案 0 :(得分:7)

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

您可以为此安排一个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);
  
      
  1. 工作是从REST API提取数据(如果可能,将其发布到LiveData对象)。
  2.   

这可以通过在您的工作人员的doWork()内同步发送您的请求来完成。我不会在您的LiveData类中使用Worker。我们稍后再说。例如,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;
}
  
      
  1. 返回数据后,检查它是否比本地数据新。
  2.   

您以同步方式获取API数据。还可以同步获取本地数据,并做任何需要比较的事情。

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

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

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

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

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

我建议您在Worker中更新您的本地数据,订阅您的工作人员身份,一旦成功,您就可以使用本地数据更新您的用户界面(如果您仍然没有订阅您的本地数据,即使用会议室)和LiveData)。

答案 1 :(得分:0)

这是最初的想法。如果我错了,请有人纠正我。

  

我的工作人员已经发布过它成功的信息,并且可能不会继续进行回调,对吧?

我们可以使用来自API响应的回调来构造工作程序的输出数据,并使用worker.setOutputData()进行设置 然后从workManager收听LiveData<WorkStatus>。从此工作状态,我们可以使用workStatus.getOutputdata()获取outputData。这些数据可以为我们提供所需的API响应。

我们可以将此响应传递给工作程序链中的下一个工作程序,以执行诸如更新本地数据库之类的任务。