android - WorkManager 如何调度 GET 请求到 REST API?

标签 android android-workmanager

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

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

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

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

最佳答案

  1. Schedule a job that runs once a day in background

您可以为此安排一个PeriodicWorkRequest,它应该使用enqueueUniquePeriodicWork 排队。这可确保同一时间只有一个特定名称的 PeriodicWorkRequest 处于 Activity 状态。

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. The job is to do a data fetch from the REST API (and post it to a LiveData object if possible).

这可以通过在您的工作人员的 doWork() 中同步发送您的请求来完成。我不会在您的 Worker 类中使用 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;
}
  1. When the data returns, check that it is newer than local data.

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

  1. Notify the user that new data is available.

如果您使用 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)

官方指南还解释了如何从您的任务返回数据,您可以使用它在您的 MutableLiveData 上调用 setValue()

我建议在您的Worker 中更新您的本地数据,订阅您的工作人员状态,一旦它成功使用本地数据更新您的 UI(如果您无论如何都没有订阅您的本地数据,即使用 Room 和 LiveData)。

编辑:关于第 4 点,定期工作请求的读取状态有点不同。它们只会在 ENQUEUEDRUNNING 之间切换,直到 CANCELLED。但永远不会有状态 SUCCEEDEDFAILED。因此监听 isFinished() 可能不是您所期望的。

关于android - WorkManager 如何调度 GET 请求到 REST API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50761374/

相关文章:

java - 与 androidx.work.logger 发生不兼容的ClassChangeError

java - 连接良好时上传图片,Android(后台进程)

java - Android 应用程序在平板手机上崩溃,但在手机上运行良好

php - 通过 PC 名称而不是本地 IP 地址访问 wamp 服务器文件-Android 应用程序

java - Android:如何循环播放音效?

工作开始后 Android 工作管理器约束发生变化

android - 使用工作管理器获取远程异常

android - 在 Android 中为定期工作管理器设置初始延迟

android - 增加 Activity 的屏幕亮度

android - 在 SQLiteDatabase.query() 中使用 String[] selectionArgs