Я разрабатываю приложение для Android, используя WorkManager (Android Jetpack) с Rx. Ниже представлен класс 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» я вызываю «cancelWorkById» после завершения работы Worker. Это правильно?
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)
}
}
}
}
Используемый вами метод getWorkInfoById возвращает ListenableFuture, а этот возвращает LiveData :
Вместо вашего цикла while вы можете просто наблюдать за рабочим статусом, наблюдая за LiveData, возвращаемым getWorkInfoByIdLiveData(), а затем вызывать emitter.onComplete() после его запуска, но у вас нет LifeCycle здесь, в вашем презентере, поэтому вы должны использовать наблюдатьForever() и позаботьтесь об удалении Наблюдателя,
Вот пример:
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)
}
Или просто используйте ListenableFuture, возвращаемый getWorkInfoById(), чтобы получить CallBack
Если вы идете по пути LiveData, то сначала объявите Observer, например myObserver, затем вызовите getWorkInfoByIdLiveData().observeForever(myObserver), а затем, когда он сработает, если он вам больше не нужен, вызовите getWorkInfosByIdLiveData.removeObserver(myObserver)
И да, использование этих LiveData допустимо, также вызов cancelWorkById() отменит вашу работу, не связанную с LiveData, это не то, что вы хотите, верно? Замените на removeObserver, как я уже сказал, и проверьте параметр данных, когда он срабатывает, возможно, он должен содержать статус (успех и т. д.).
Хм... Я понял, но я все еще не знаю, где я могу вызвать "removeObserver". Не могли бы вы дать мне больше руководства, пожалуйста? ...
Спасибо, я редактирую вопрос с новым кодом, которым вы руководствуетесь. Я не знаю, как я могу «удалить наблюдателя». Поэтому я написал «cancelWorkById» в «observeForever». Не могли бы вы сказать мне, все ли в порядке?