Как наблюдать последний испущенный WorkManager getWorkInfoByIdLiveData с Android Worker - PullRequest
3 голосов
/ 07 января 2020

В моем текущем Android приложении занято

archWorkerRuntimeVersion = '2.3.0-beta02'

api "androidx.work:work-runtime:$archWorkerRuntimeVersion"
api "androidx.work:work-runtime-ktx:$archWorkerRuntimeVersion"

Я наблюдаю за рабочим состоянием через LiveData следующим образом: -

 WorkManager.getInstance(applicationContext).getWorkInfoByIdLiveData(experimentRequest.id).observe(lifeCycleOwner, observer)

, где lifeCycleOwner - моя активность, а наблюдатель - состояние c val

private val observer = object : Observer<WorkInfo> {
    override fun onChanged(it: WorkInfo?) {
        Log.e("Worker", "this is our single observer $it $this")
        if (it == null) return
        repository.storeCurrentWorkId(it.id)
    }
}

комментарий для observe(lifeCycleOwner, observer) гласит: -

/**
 * Adds the given observer to the observers list within the lifespan of the given
 * owner. The events are dispatched on the main thread. If LiveData already has data
 * set, it will be delivered to the observer.
 * <p>
 * The observer will only receive events if the owner is in {@link Lifecycle.State#STARTED}
 * or {@link Lifecycle.State#RESUMED} state (active).
 * <p>
 * If the owner moves to the {@link Lifecycle.State#DESTROYED} state, the observer will
 * automatically be removed.
 * <p>
 * When data changes while the {@code owner} is not active, it will not receive any updates.
 * If it becomes active again, it will receive the last available data automatically.
 * <p>
 * LiveData keeps a strong reference to the observer and the owner as long as the
 * given LifecycleOwner is not destroyed. When it is destroyed, LiveData removes references to
 * the observer &amp; the owner.
 * <p>
 * If the given owner is already in {@link Lifecycle.State#DESTROYED} state, LiveData
 * ignores the call.
 * <p>
 * If the given owner, observer tuple is already in the list, the call is ignored.
 * If the observer is already in the list with another owner, LiveData throws an
 * {@link IllegalArgumentException}.
 *
 * @param owner    The LifecycleOwner which controls the observer
 * @param observer The observer that will receive the events
 */

, хотя это утверждение не соответствует действительности, хотя

If it becomes active again, it will receive the last available data automatically.

Если только Я неправильно понимаю, что это значит.

Я понял, что, когда моя активность снова станет активной, я получу самые последние (последние) доступные данные.

В результате моего тестирования это не тот случай, единственные данные, которые я получаю, это любые новые данные, которые отправляются ПОСЛЕ того, как моя активность снова становится активной.

Что я делаю не так?

Есть ли способ получить последние данные, когда моя активность станет активной?

ОБНОВЛЕНИЕ

Я создал следующее простое Android приложение, чтобы продемонстрировать эту проблему.

Это Android Приложение состоит из трех действий.

Dummy Main Activity
Worker Activity
Dummy Second Activity

My В тестах задействовано

1). Starting App with Dummy Main Activity, navigating to WorkerActivity, starting Worker and waiting for the worker to SUCCEED

2). Starting App with Dummy Main Activity, navigating to WorkerActivity, starting Worker, then navigate to Dummy Second Activity and returning to WorkerActivity

3). Starting App with Dummy Main Activity, navigating to WorkerActivity, starting Worker, then return to Dummy Main Activity and returning to WorkerActivity

Рабочее действие запускает и наблюдает за LiveData, как показано ниже

class WorkerActivity : AppCompatActivity(), Observer<WorkInfo?> {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_ninth)

        findViewById<Button>(R.id.start_work_tags_button).setOnClickListener {
            doSomeWork()
        }

        findViewById<Button>(R.id.start_work_button).setOnClickListener {
            startActivity(Intent(this@WorkerActivity, Seventh::class.java))
        }

    }

    private fun doSomeWork() {
        val ninthRequest: OneTimeWorkRequest = manufactureOneTimeWorkRequest(NinthWorker::class.java)

        WorkManager.getInstance(applicationContext)
            .beginUniqueWork(UNIQUE_WORK_NAME, ExistingWorkPolicy.KEEP, ninthRequest)
            .enqueue()

        val workInfos = WorkManager.getInstance(applicationContext).getWorkInfoByIdLiveData(ninthRequest.id)
        workInfos.observe(this as LifecycleOwner, this as Observer<in WorkInfo>)
    }

    private fun manufactureOneTimeWorkRequest(klazz: Class<out CoroutineWorker>): OneTimeWorkRequest {
        return OneTimeWorkRequest.Builder(klazz).addTag(WORK_IN_PROGRESS_TAG + "${UUID.randomUUID()}").build()
    }

    companion object {
        private const val WORK_IN_PROGRESS_TAG = "SYNC-IN-PROGRESS-TAG"
        private const val UNIQUE_WORK_NAME = "SYNC-UNIQUE_WORK_NAME"
    }

    override fun onChanged(workInfo: WorkInfo?) {
        Log.e("NINTH", "onChanged($workInfo)")

    }
}

Два «фиктивных» действия используются, чтобы позволить WorkerActivity в качестве владельца LifeCycle стать "in active"

Журналы, которые я вижу для теста 1). показаны здесь: -

2020-01-14 10:54:36.114 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityCreated() org.vulgaris.behave.sixth.DummyMainActivity@cdc2743
2020-01-14 10:54:36.228 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStarted() org.vulgaris.behave.sixth.DummyMainActivity@cdc2743
2020-01-14 10:54:36.230 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityResumed() org.vulgaris.behave.sixth.DummyMainActivity@cdc2743
2020-01-14 10:54:43.324 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityPaused() org.vulgaris.behave.sixth.DummyMainActivity@cdc2743
2020-01-14 10:54:43.343 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityCreated() org.vulgaris.behave.ninth.WorkerActivity@abd837d
2020-01-14 10:54:43.386 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStarted() org.vulgaris.behave.ninth.WorkerActivity@abd837d
2020-01-14 10:54:43.387 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityResumed() org.vulgaris.behave.ninth.WorkerActivity@abd837d
2020-01-14 10:54:43.776 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStopped() org.vulgaris.behave.sixth.DummyMainActivity@cdc2743
2020-01-14 10:54:43.778 23452-23452/org.vulgaris.behave E/APPLICATION: onActivitySaveInstanceState() org.vulgaris.behave.sixth.DummyMainActivity@cdc2743
2020-01-14 10:54:48.812 23452-23452/org.vulgaris.behave E/WorkerActivity: onChanged(WorkInfo{mId='f3655bdd-3b1d-4e59-a896-3798ec860856', mState=ENQUEUED, mOutputData=Data {}, mTags=[org.vulgaris.behave.worker.NinthWorker, SYNC-IN-PROGRESS-TAG691b47cb-143f-42fc-8d88-903880e1f699], mProgress=Data {}})
2020-01-14 10:54:48.826 23452-23584/org.vulgaris.behave E/NinthWorker:  doWork 56fd9de0-ad8e-4275-b8a0-28e0cd045b9c  inputData = Data {}
2020-01-14 10:54:48.829 23452-23452/org.vulgaris.behave E/WorkerActivity: onChanged(WorkInfo{mId='f3655bdd-3b1d-4e59-a896-3798ec860856', mState=RUNNING, mOutputData=Data {}, mTags=[org.vulgaris.behave.worker.NinthWorker, SYNC-IN-PROGRESS-TAG691b47cb-143f-42fc-8d88-903880e1f699], mProgress=Data {}})
2020-01-14 10:55:48.851 23452-23583/org.vulgaris.behave I/WM-WorkerWrapper: Worker result SUCCESS for Work [ id=f3655bdd-3b1d-4e59-a896-3798ec860856, tags={ org.vulgaris.behave.worker.NinthWorker, SYNC-IN-PROGRESS-TAG691b47cb-143f-42fc-8d88-903880e1f699 } ]
2020-01-14 10:55:48.902 23452-23452/org.vulgaris.behave E/WorkerActivity: onChanged(WorkInfo{mId='f3655bdd-3b1d-4e59-a896-3798ec860856', mState=SUCCEEDED, mOutputData=Data {}, mTags=[org.vulgaris.behave.worker.NinthWorker, SYNC-IN-PROGRESS-TAG691b47cb-143f-42fc-8d88-903880e1f699], mProgress=Data {}})

Журналы, которые я вижу для теста 2). здесь показаны: -

2020-01-14 10:59:20.726 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityCreated() org.vulgaris.behave.sixth.DummyMainActivity@6a03dee
2020-01-14 10:59:20.780 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStarted() org.vulgaris.behave.sixth.DummyMainActivity@6a03dee
2020-01-14 10:59:20.781 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityResumed() org.vulgaris.behave.sixth.DummyMainActivity@6a03dee
2020-01-14 10:59:23.781 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityPaused() org.vulgaris.behave.sixth.DummyMainActivity@6a03dee
2020-01-14 10:59:23.799 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityCreated() org.vulgaris.behave.ninth.WorkerActivity@2fe5636
2020-01-14 10:59:23.836 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStarted() org.vulgaris.behave.ninth.WorkerActivity@2fe5636
2020-01-14 10:59:23.837 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityResumed() org.vulgaris.behave.ninth.WorkerActivity@2fe5636
2020-01-14 10:59:24.209 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStopped() org.vulgaris.behave.sixth.DummyMainActivity@6a03dee
2020-01-14 10:59:24.210 23452-23452/org.vulgaris.behave E/APPLICATION: onActivitySaveInstanceState() org.vulgaris.behave.sixth.DummyMainActivity@6a03dee
2020-01-14 10:59:30.564 23452-23452/org.vulgaris.behave E/WorkerActivity: onChanged(WorkInfo{mId='da800c85-485d-4cb5-9931-d3f20edf611e', mState=ENQUEUED, mOutputData=Data {}, mTags=[SYNC-IN-PROGRESS-TAG6c6ff5e2-b8a7-4f73-99e6-c112f7598287, org.vulgaris.behave.worker.NinthWorker], mProgress=Data {}})
2020-01-14 10:59:30.585 23452-23452/org.vulgaris.behave E/WorkerActivity: onChanged(WorkInfo{mId='da800c85-485d-4cb5-9931-d3f20edf611e', mState=RUNNING, mOutputData=Data {}, mTags=[SYNC-IN-PROGRESS-TAG6c6ff5e2-b8a7-4f73-99e6-c112f7598287, org.vulgaris.behave.worker.NinthWorker], mProgress=Data {}})
2020-01-14 10:59:30.585 23452-23585/org.vulgaris.behave E/NinthWorker:  doWork 6407357d-0471-41ee-8ea2-6cedeaf1e463  inputData = Data {}
2020-01-14 10:59:31.749 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityPaused() org.vulgaris.behave.ninth.WorkerActivity@2fe5636
2020-01-14 10:59:31.767 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityCreated() org.vulgaris.behave.seventh.DummySecondActivity@3572f3a
2020-01-14 10:59:31.834 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStarted() org.vulgaris.behave.seventh.DummySecondActivity@3572f3a
2020-01-14 10:59:31.835 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityResumed() org.vulgaris.behave.seventh.DummySecondActivity@3572f3a
2020-01-14 10:59:32.211 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStopped() org.vulgaris.behave.ninth.WorkerActivity@2fe5636
2020-01-14 10:59:32.211 23452-23452/org.vulgaris.behave E/APPLICATION: onActivitySaveInstanceState() org.vulgaris.behave.ninth.WorkerActivity@2fe5636
2020-01-14 10:59:33.112 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityPaused() org.vulgaris.behave.seventh.DummySecondActivity@3572f3a
2020-01-14 10:59:33.128 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStarted() org.vulgaris.behave.ninth.WorkerActivity@2fe5636
2020-01-14 10:59:33.129 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityResumed() org.vulgaris.behave.ninth.WorkerActivity@2fe5636

I SHOULD SEE "WorkerActivity: onChanged(WorkInfo{mId='da800c85-485d-4cb5-9931-d3f20edf611e', mState=RUNNING, mOutputData=Data {}, mTags=[SYNC-IN-PROGRESS-TAG6c6ff5e2-b8a7-4f73-99e6-c112f7598287, org.vulgaris.behave.worker.NinthWorker], mProgress=Data {}})" HERE

2020-01-14 10:59:33.510 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStopped() org.vulgaris.behave.seventh.DummySecondActivity@3572f3a
2020-01-14 10:59:33.512 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityDestroyed() org.vulgaris.behave.seventh.DummySecondActivity@3572f3a
2020-01-14 11:00:30.624 23452-23583/org.vulgaris.behave I/WM-WorkerWrapper: Worker result SUCCESS for Work [ id=da800c85-485d-4cb5-9931-d3f20edf611e, tags={ SYNC-IN-PROGRESS-TAG6c6ff5e2-b8a7-4f73-99e6-c112f7598287, org.vulgaris.behave.worker.NinthWorker } ]
2020-01-14 11:00:30.673 23452-23452/org.vulgaris.behave E/WorkerActivity: onChanged(WorkInfo{mId='da800c85-485d-4cb5-9931-d3f20edf611e', mState=SUCCEEDED, mOutputData=Data {}, mTags=[SYNC-IN-PROGRESS-TAG6c6ff5e2-b8a7-4f73-99e6-c112f7598287, org.vulgaris.behave.worker.NinthWorker], mProgress=Data {}})

Это неверно для теста 2). как я должен видеть "... последние доступные данные автоматически." когда WorkerActivity возобновлено

Почему наблюдатель LiveData не запускается автоматически при возобновлении WorkerActivity?

Ответы [ 2 ]

0 голосов
/ 16 января 2020

Причина, по которой ваш обозреватель не вызван, заключается в том, что жизненный цикл WorkerActivity не переходит в состояние Lifecycle.State.DESTROYED в тесте 2) (просто потому, что если он действительно переходит в Lifecycle.State.DESTROYED, то наблюдатель будет удален, и он не может быть вызван с mState=SUCCEEDED после завершения работника). Следовательно, наблюдатель не удален, он просто продолжает наблюдать LiveData в течение всего времени, пока работник не закончил.

Так что нет никаких противоречий с документацией:

 * When data changes while the {@code owner} is not active, it will not receive any updates.
 * If it becomes active again, it will receive the last available data automatically.

Ваши данные не изменились во время изменения активности наблюдателя, WorkInfo все время находится в рабочем состоянии.

0 голосов
/ 15 января 2020

Кажется, что ваш наблюдатель разрушается, когда вы переключаетесь между действиями. Я не могу на 100% гарантировать, что это то, что происходит, но на основании логов есть довольно хороший шанс, что он хотя бы достигнет Lifecycle.DESTROYED состояния

. Вы можете использовать чек в вашем onClick прямо перед тем, как установить наблюдатель для hasActiveObservers ()


Наблюдатель связан с состоянием жизненного цикла.

LiveData считает, что наблюдатель, представленный классом Observer, находится в состоянии active , если его жизненный цикл находится в STARTED или RESUMED состояние.

Это означает, что вы будете получать обновления, если ваша активность находится в одном из этих состояний. Если мы посмотрим на условия каждого из этих состояний, то они

RESUMED

  • это состояние достигается после вызова onResume .

STARTED

  • Для действия это состояние достигается в двух случаях:
  • после вызова onStart;
  • прямо перед вызовом onPause.

На самом деле, исходя из этого, вы должны увидеть, как ваш наблюдатель будет вызван сразу после onStart()

Однако, в документации также перечислены

Если владелец перейдет в состояние {@link Lifecycle.State # DESTROYED}, наблюдатель будет * автоматически удален.

, что означает, что ваш наблюдатель больше не будет получать обновления.

УНИЧТОЖЕНО

  • это состояние достигнуто прямо перед вызовом onDestroy активности.

Теперь ваши логи не показывать onActivityDestroyed, но, по-видимому, есть хороший признак того, что он, по крайней мере, входит в Lifecycle.STATE == DESTROYED на основании:

2020-01-14 10:59:32.211 23452-23452/org.vulgaris.behave E/APPLICATION: onActivityStopped() org.vulgaris.behave.ninth.WorkerActivity@2fe5636

и

2020-01-14 10:59:32.211 23452-23452/org.vulgaris.behave E/APPLICATION: onActivitySaveInstanceState() org.vulgaris.behave.ninth.WorkerActivity@2fe5636

Надеюсь, это помогает!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...