Наблюдатель за рабочим статусом всегда в исправном состоянии

Я пытаюсь наблюдать за моим workers но они всегда в queued состояние или когда-нибудь это RUNNING но никогда SUCCEED или же FAILED,

является workStatus.state от возвращения в doWork() или это другое?

это мой рабочий скрипт:

package com.mockie.daikokuten.sync.workers

import androidx.work.Worker


class TestWorker:Worker()
{

override fun doWork():Worker.Result
{
    return Worker.Result.SUCCESS
}

}

это скрипт для наблюдения за рабочими:

 val test = PeriodicWorkRequest.Builder(
            TestWorker::class.java,
            PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
            TimeUnit.MILLISECONDS)
            .addTag("test_worker")
            .build()

    WorkManager.getInstance()?.enqueueUniquePeriodicWork("test_worker", ExistingPeriodicWorkPolicy.KEEP, test)

    WorkManager.getInstance()!!.getStatusesByTag("test_worker")
            .observe(this, Observer { workStatus ->
                if (workStatus != null)
                {
                    for(ws in workStatus)
                    {
                        Log.d(":dump2 id ", ws.id.toString())
                        Log.d(":dump2 tag", ws.tags.toString())
                        Log.d(":dump2 state", ws.state.toString())
                    }
                }
            })

это результат в Logcat:

 07-23 17:12:30.901 29740-29740/com.mockie.daikokuten D/:dump2 id: 5c6297f7-11d8-4f2f-a327-773672a7435c
 07-23 17:12:30.901 29740-29740/com.mockie.daikokuten D/:dump2 tag: [test_worker, com.mockie.daikokuten.sync.workers.TestWorker]
 07-23 17:12:30.901 29740-29740/com.mockie.daikokuten D/:dump2 state: ENQUEUED

4 ответа

Решение

Для вашего периодического запроса на работу вы должны увидеть

ENQUEUED - RUNNING - ENQUEUED

где последний ENQUEUED - это состояние следующего рабочего запроса.

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

Для разового запроса на работу вы видите

ENQUEUED - RUNNING - SUCCEEDED

или что вы возвращаете в doWork ().

(Android 8.1 API 27, 1.0.0-alpha04)

Это для тех, у кого возникают проблемы с получением выходных данных от периодической работы. Это больше похоже на взлом. В вашем Worker просто определите статические изменяемые живые данные. В месте, где вы наблюдаете состояние своей работы, наблюдайте эти данные в реальном времени, когда ваше состояние превращается в "РАБОТА".

Вот шаблон:

  1. Фактический Работник:
public class SomeWorker extends Worker{

   //This live data can be of any type. I'm setting Boolean
   Public static MutableLiveData<Boolean> outputObservable = new MutableLiveData();
   private boolean output_boolean;
   try{
       //Do you work here post your result to the live data
       output_boolean = SomeTaskThatReturnsABoolean();
       outputObservable.postValue(output_boolean);
       return Result.Success();
   }catch(Exception e){
       e.printStackTrace();
       outputObservable.postValue(!output_boolean);
       return Result.Failure();
    }
}

  1. Ваша деятельность, которая отслеживает информацию этого работника:
//In YourActivity class inside OnCreate
mWorkManager.getWorkInfoForUniqueWorkLiveData(YOUR_TAG).observe (this,
   new Observer<List<WorkInfo>>(){
       @Override
       public void onChanged(@Nullable List<WorkInfo> workInfos) {
          if(workInfos!=null && (!(workInfos.isEmpty()))) {
             WorkInfo info = workInfos.get(0);
             switch(info.getState()){
               case ENQUEUED:
                   break;
               case RUNNING:
                   SomeWorker.outputObservable.observe(YourActivity.this,
                      new Observer<Boolean>(){
                      @Override
                       public void onChanged(@Nullable Boolean aBoolean) {
                           //EDIT: Remove the observer of the worker otherwise 
                           //before execution of your below code, the observation might switch
                           mWorkManager.getWorkInfoForUniqueWorkLiveData(YOUR_TAG).removeObservers(YourActivity.this);
                           if(aBoolean)
                             //Do whatever you have to if it's true
                           else
                             //Do whatever you have to if it's false
                           }
                      }
                   );
             }
          }
       }
   }
);

Таким образом, вы можете наблюдать за своими результатами, когда состояние работы находится в процессе выполнения, прежде чем оно будет переведено обратно в очередь.

Приведенный выше ответ является правильным. Для PeriodicWork вы должны увидеть:

ENQUEUED -> RUNNING -> ENQUEUED

Тем не менее, есть ошибка в alpha04 что приводит к PeriodicWork не работать на API >= 23. Это будет исправлено в alpha05, Для получения дополнительной информации посмотрите на https://issuetracker.google.com/issues/111195153.

ВАЖНО: По состоянию на пару дней назад: alpha05 отправлен. Эта ошибка исправлена.

Как уже говорили другие, это действительно никогда не достигнетSUCCEEDEDсостояние, поэтому вы никогда не сможете наблюдать какое бы значение вы ни возвращали в своем Result.success(yourData).

Но надежда еще не потеряна! Фактически вы можете наблюдать данные вPeriodicWorkRequests без каких-либо хаков, таких как настройка статических наблюдаемых или запись/чтение данных в/из общих настроек или локальной базы данных.

В doWork мы устанавливаем данные через setProgress и добавляем неблокирующую задержку с помощью функции задержки() Coroutine перед возвратом результата:

      override suspend fun doWork(): Result {
        // do long running work, like waiting for the result of an async api call
        val outputData: Data = Data.Builder()
            .putString("asyncString", asyncString)
            .build()
        
        setProgress(outputData)
        delay(1000)
        Result.success()
    }

Затем вы можете наблюдать за LiveData (или потоком Kotlin), полученным с помощью getWorkInfoByIdLiveData, и читать данные, которые вы установили в setProgress WorkInfo, с помощью getProgress()WorkInfo:

      val workRequest = PeriodicWorkRequestBuilder<MyWorker>(1, TimeUnit.HOURS)
    .setInputData(workerData)
    .build()

WorkManager.getInstance(context).enqueue(workRequest)
val workInfo = WorkManager.getInstance(context).getWorkInfoByIdLiveData(workRequest.id).asFlow()

scope.launch {
    updateWorkInfo.collect { workInfo ->
        workInfo.progress.getString("asyncString", "")
    }
}

Задержка в 1 секунду, которую мы установили в doWork() перед возвратом Result.success(), необходима, поскольку при вызове Result.success() работа немедленно завершается, и ее состояние становитсяENQUEUED; у вас не будет достаточно времени, чтобы наблюдать за текущей работой.

Подробнее:https://developer.android.com/guide/background/persistent/how-to/observe .