21

我是新架构组件 WorkManager 的新手,我通过 Retrofit 和 RxJava 进行 API 调用。

我的用例是从后端获取新帖子,然后显示通知并更新小部件。

所以 Worker 类的 doWork() 方法中的代码可能看起来像这样。

@NonNull
  @Override
  public Result doWork() {
    AppDependencies appDependencies = new AppDependencies((Application) getApplicationContext());
    Repository repository = appDependencies.getRepository();

    repository.getNewPosts()
        .flatMap(newPosts -> repository.inserPosts(newPosts).toObservable())
        .doOnError(Timber::e)
        //if success - > return  Result.SUCCESS,
        // -> show notification
        // -> update widget
        // error-> return Result.Failure
        .dontKnowWhatBestNextThing; //blocking or subscribing

    //if we reached here then Retry
    return Result.RETRY;
  }

我的问题是在 Worker 类中使用 RxJava 代码的正确方法是什么,因为 doWork() 方法有一个返回值,所以我必须使 Rx 代码同步吗?

如果我使用的是非阻塞 Rx 方法,我该如何返回值(成功 - 失败 - 重试)

4

5 回答 5

38

从 WorkManager 版本开始1.0.0-alpha12,他们添加了一个名为的新工件work-rxjava2,其中包含RxWorker专门用于此目的的类。ListenableWorker这是期待的一个特例Single<Result>

要实现它,首先确保将正确的工件包含到您的build.gradle

dependencies {
   ...
   implementation "android.arch.work:work-runtime-ktx:$work_version"
   implementation "android.arch.work:work-rxjava2:$work_version"
}

并实施你的RxWorker

class MyRxWorker(context : Context, params : WorkerParameters) : RxWorker(context, params) {

    val remoteService = RemoteService()

    override fun createWork(): Single<Result> {
        return remoteService.getMySingleResponse()
                .doOnSuccess { /* process result somehow */ }
                .map { Result.success() }
                .onErrorReturn { Result.failure() }
    }
}
于 2018-12-16T17:56:27.273 回答
6

编辑: WorkManager 现在正式支持RxWorker. 请查看上面的答案以获取更多信息。

doWork发生在后台线程上。所以封锁是安全的。您应该等待Observable完成,然后再返回Result.

我们还在努力使用异步 API 使这更容易。敬请关注。

于 2018-08-09T20:17:17.137 回答
1

是的,使 Rx 代码同步。doWork的文档很少,但描述

覆盖此方法以进行实际的后台处理。

暗示它被预期或至少被允许阻止。doWork当然,在解决网络请求之前,您无法知道应该返回什么。

于 2018-08-09T00:16:15.947 回答
0

您可以将 Rxjava 和 Coroutine 与 Work Manager 一起使用。看看这篇中等帖子。希望它会帮助你。谢谢你。

于 2021-02-18T12:04:51.810 回答
0

我找到了解决方案。您应该使用 RxWorker 或 SettableFuture 进行异步作业

这是我获取当前位置的解决方案。像魅力一样工作

class LocationWorker(context: Context, private val workerParams: WorkerParameters) :
ListenableWorker(context, workerParams) {

lateinit var mFuture: SettableFuture<ListenableWorker.Result>
private var fusedLocationProviderClient = FusedLocationProviderClient(context)

@SuppressLint("RestrictedApi", "MissingPermission")
override fun startWork(): ListenableFuture<Result> {
    val uniqueId = workerParams.inputData.getString(UNIQUE_ID_KEY)
    mFuture = SettableFuture.create()
    Timber.d("mFutureStart")
    fusedLocationProviderClient.lastLocation.addOnSuccessListener { location ->
        Timber.d("location == $location")
        if (location != null) {
            mFuture.set(Result.success())
        } else mFuture.set(Result.failure())
      }
    return mFuture
   }
}
于 2019-02-26T04:38:45.273 回答