首页 > 解决方案 > Android:如何处理 WorkManager Rx 的结果?

问题描述

我正在使用带有 Rx 的 WorkManager (Android Jetpack) 开发一个 Android 应用程序。下面是 Worker 类。

class ImageRxWorker(
    appContext: Context,
    private val workerParams: WorkerParameters
) : RxWorker(appContext, workerParams) {

    override fun createWork(): Single<Result> = Single.create<Result> { emitter -

        // do the job

        emitter.onSuccess(Result.success())
    }

}

它工作正常,没有问题。但我想知道的是如何处理结果?

class MainPresenter(
    private val view: MainActivity,
    private val workManager: WorkManager = WorkManager.getInstance()
) : MainContract.Presenter {

    override fun startWork(): Completable {
        view.showToastMessage(R.string.worker_started)

        return Completable.create { emitter ->
            val uploadWorkRequest = OneTimeWorkRequestBuilder<ImageRxWorker>().build()
            workManager.enqueue(uploadWorkRequest)
            emitter.onComplete() // This is not exit immediately.
        }
    }

}

我找到了“addListener”、“result”,但我不知道如何使用它们。我试图用谷歌搜索,但找不到任何好的参考。来人帮帮我!


我想...我找到了解决方案之一。

有用!!!

但是……它……很丑……而且不聪明……

(在我的应用程序中,我不使用 LiveData。)

    override fun startWork(): Completable {
        view.showToastMessage(R.string.worker_started)

        return Completable.create { emitter ->
            Log.d(TAG, "[WM][Presenter] startWork - start")
            val workRequest = OneTimeWorkRequestBuilder<ImageRxWorker>()
                .setInputData(workDataOf("TIME" to 1000L))
                .build()

            workManager.enqueue(workRequest)

            while (workManager.getWorkInfoById(workRequest.id).get().state != WorkInfo.State.SUCCEEDED) {
                // Should I really polling?
                Thread.sleep(1000)
                Log.d(TAG, "[WM][Presenter] not yet......")
            }

            Log.d(TAG, "[WM][Presenter] complete")
            emitter.onComplete()
        }
    }

哇,这是“用户一号”的答案编写的第三个代码。它工作正常,看起来比第二个代码更好。因为我的应用程序不使用“LiveData”,所以我无法确保此代码是否有效。

在“observeForever”中,我在 Worker 完成后调用“cancelWorkById”。这是对的吗?

    override fun startWork(): Completable {
        view.showToastMessage(R.string.worker_started)

        return Completable.create { emitter ->
            Log.d(TAG, "[WM][Presenter] startWork - start")
            val workRequest = OneTimeWorkRequestBuilder<ImageRxWorker>()
                .setInputData(workDataOf("TIME" to 1000L))
                .build()

            workManager.enqueue(workRequest)

            workManager.getWorkInfoByIdLiveData(workRequest.id).observeForever { workInfo ->
                workInfo?.outputData?.getString("key")?.let { data ->
                    Log.d(TAG, "[WM][Presenter] startWork - complete: $data")
                    emitter.onComplete()
                    workManager.cancelWorkById(workRequest.id)
                }
            }
        }
    }

标签: androidkotlinrx-javarx-java2android-workmanager

解决方案


您使用 getWorkInfoById 的方法返回一个 ListenableFuture,而这个返回一个 LiveData:

https://developer.android.com/reference/androidx/work/WorkManager.html#getWorkInfoByIdLiveData(java.util.UUID)

而不是您的while循环,您可以通过观察getWorkInfoByIdLiveData()返回的LiveData来简单地观察工作状态,然后在触发后调用emitter.onComplete(),但是您的演示者中没有LifeCycle,因此您应该使用observeForever()并注意移除观察者,

这是一个例子:

workManager.getWorkInfoByIdLiveData(workRequest.id)
 .observeForever(object : Observer<WorkInfo> {
        override fun onChanged(workInfo : WorkInfo?) {
           if(workInfo.state == WorkInfo.State.SUCCEEDED) {
             ////The Work result is a Success
            }
            /* Here We remove the Observer if Not needed anymore
                 'this' here = the Observer */
         workManager.getWorkInfoByIdLiveData(workRequest.id)
          .removeObserver(this) 
        }

或者简单地使用 getWorkInfoById() 返回的 ListenableFuture 来获取 CallBack


推荐阅读