23

我已经查看了 WorkManager 的代码实验室以及此处的一些示例,但是我所看到的代码中的所有内容都与在设备上本地工作或上传到服务器的工作有关,而不是下载数据并响应收到的数据. 在开发人员指南中甚至说,“例如,一个应用程序可能需要不时从网络下载新资源”,所以我认为它非常适合这项任务。我的问题是 WorkManager 是否可以处理以下情况,如果不能,处理它的正确工具是什么:

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

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

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 或其他更合适的东西。

4

2 回答 2

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

您可以为此安排一个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 对象)。

这可以通过在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. 当数据返回时,检查它是否比本地数据更新。

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

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

如果您安排一个任务,WorkManager它保证运行,即使您的应用程序被强制退出或设备重新启动。因此,您的任务可能会在您的应用未运行时完成。如果您想在任何情况下通知用户,您可以发送通知。如果您想在某个屏幕内通知用户,您可以订阅您的任务状态。例如像这样(取自官方指南):

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,订阅您的工作人员状态,一旦成功,使用本地数据更新您的 UI(如果您没有订阅本地数据,即使用 Room 和LiveData)。

编辑:参考第 4 点,定期工作请求的读取状态有点不同。他们只是在ENQUEUEDRUNNINGuntil之间切换CANCELLED。但永远不会有状态SUCCEEDEDFAILED。因此,聆听isFinished()可能不是您所期望的。

于 2018-07-13T18:16:25.920 回答
0

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

我的工作人员已经发布了它是成功的,它可能不会继续回调,对吧?

我们可以使用来自 API 响应的回调,构造工作人员的输出数据并使用它进行设置,worker.setOutputData() 然后监听LiveData<WorkStatus>来自 workManager。从这个工作状态我们可以得到 outputData 使用,workStatus.getOutputdata()。这些数据可以给我们想要的 API 响应。

我们可以将此响应传递给工作链中的下一个工作人员,以执行更新本地数据库等任务。

于 2018-06-19T13:05:38.563 回答