Android WorkManager观察进度

Android WorkManager观察进度,android,android-workmanager,Android,Android Workmanager,我在应用程序中使用WorkManager进行延迟工作。 整个工作被划分为若干个链接的工人,我很难向用户显示工人的进度(使用进度条) 我尝试创建一个标记并将其添加到不同的Worker中,workers内部通过该标记更新进度,但在调试时,我始终获得的进度为“0” 我注意到的另一件事是,每当我开始工作时(即使工人完成了他们的工作),workManager的工作信息列表会越来越大 这是我的密码: //inside view model private val workManager = Work

我在应用程序中使用WorkManager进行延迟工作。 整个工作被划分为若干个链接的工人,我很难向用户显示工人的进度(使用进度条)

我尝试创建一个标记并将其添加到不同的Worker中,workers内部通过该标记更新进度,但在调试时,我始终获得的进度为“0”

我注意到的另一件事是,每当我开始工作时(即使工人完成了他们的工作),workManager的工作信息列表会越来越大

这是我的密码:

//inside view model
    private val workManager = WorkManager.getInstance(appContext)
    internal val progressWorkInfoItems: LiveData<List<WorkInfo>>


    init
    {
        progressWorkInfoItems = workManager.getWorkInfosByTagLiveData(TAG_SAVING_PROGRESS)
    }

    companion object
    {
        const val TAG_SAVING_PROGRESS = "saving_progress_tag"
    }

      //inside a method
        var workContinuation = workManager.beginWith(OneTimeWorkRequest.from(firstWorker::class.java))

        val secondWorkRequest = OneTimeWorkRequestBuilder<SecondWorker>()
        secondWorkRequest.addTag(TAG_SAVING_PROGRESS)
        secondWorkRequest.setInputData(createData())
        workContinuation = workContinuation.then(secondWorkRequest.build())

        val thirdWorkRequest = OneTimeWorkRequestBuilder<ThirdWorker>()
        thirdWorkRequest.addTag(TAG_SAVING_PROGRESS)
        thirdWorkRequest.setInputData(createData())
        workContinuation = workContinuation.then(thirdWorkRequest.build())

        workContinuation.enqueue()

//inside the Activity

viewModel.progressWorkInfoItems.observe(this, observeProgress())

    private fun observeProgress(): Observer<List<WorkInfo>>
    {
        return Observer { listOfWorkInfo ->
            if (listOfWorkInfo.isNullOrEmpty()) { return@Observer }

            listOfWorkInfo.forEach { workInfo ->
                if (WorkInfo.State.RUNNING == workInfo.state)
                {
                    val progress = workInfo.progress.getFloat(TAG_SAVING_PROGRESS, 0f)
                    progress_bar?.progress = progress
                }
            }
        }
    }

//inside the worker

    override suspend fun doWork(): Result = withContext(Dispatchers.IO)
    {
        setProgress(workDataOf(TAG_SAVING_PROGRESS to 10f))
        ...
        ...
        Result.success()
    }
//内部视图模型
private val workManager=workManager.getInstance(appContext)
内部val ProgressWorkInfo项目:LiveData
初始化
{
progressWorkInfoItems=workManager.getWorkInfosByTagLiveData(标记\保存\进度)
}
伴星
{
const val TAG_SAVING_PROGRESS=“SAVING_PROGRESS_TAG”
}
//方法内部
var workContinuation=workManager.beginWith(OneTimeWorkRequest.from(firstWorker::class.java))
val secondWorkRequest=OneTimeWorkRequestBuilder()
secondWorkRequest.addTag(标记保存进度)
secondWorkRequest.setInputData(createData())
workContinuation=workContinuation.then(secondWorkRequest.build())
val thirdWorkRequest=OneTimeWorkRequestBuilder()
thirdWorkRequest.addTag(标记保存进度)
thirdWorkRequest.setInputData(createData())
workContinuation=workContinuation.then(thirdWorkRequest.build())
workContinuation.enqueue()
//活动内部
viewModel.ProgressWorkInfo.observe(这是observeProgress())
私人娱乐observeProgress():Observer
{
返回观察者{listOfWorkInfo->
如果(listOfWorkInfo.isNullOrEmpty()){return@Observer }
listOfWorkInfo.forEach{workInfo->
if(WorkInfo.State.RUNNING==WorkInfo.State)
{
val progress=workInfo.progress.getFloat(标记保存进度,0f)
进度条?进度=进度
}
}
}
}
//工人内部
重写suspend fun doWork():Result=withContext(Dispatchers.IO)
{
设置进度(workDataOf(标记保存进度至10f))
...
...
结果:成功()
}

设置进度的方法是观察单个工人的中间进度(如中所述):

只能在ListenableWorker运行时观察和更新进度信息

因此,只有在工作人员处于活动状态时,进度信息才可用(例如,它不处于像
成功
失败
取消
)这样的终端状态)


我的建议是使用工人的唯一ID来识别链中哪个工人尚未处于终端状态。您可以使用
WorkRequest
的方法来检索其唯一ID。

setProgress
方法用于观察单个工作者的中间进度(如中所述):

只能在ListenableWorker运行时观察和更新进度信息

因此,只有在工作人员处于活动状态时,进度信息才可用(例如,它不处于像
成功
失败
取消
)这样的终端状态)


我的建议是使用工人的唯一ID来识别链中哪个工人尚未处于终端状态。您可以使用
WorkRequest
的方法来检索其唯一ID。

根据我的分析,我发现您总是得到
0

  • setProgress
    设置在worker的
    doWork()
    中的
    Result.success()
    之前,然后它将丢失,您永远无法在侦听器中获得该值。这可能是因为工作进程的状态现在为“已成功”
  • 工人正在几秒钟内完成工作
让我们看看下面的代码

class Worker1(context: Context, workerParameters: WorkerParameters) : Worker(context,workerParameters) {

override fun doWork(): Result {

    setProgressAsync(Data.Builder().putInt("progress",10).build())
    for (i in 1..5) {
        SystemClock.sleep(1000)
    }
    setProgressAsync(Data.Builder().putInt("progress",50).build())
    SystemClock.sleep(1000)
    return Result.success()
  }
}
在上述代码中

  • 如果只删除第一个sleep方法,那么侦听器只会获得progres
    50
  • 如果只删除第二个sleep方法,则侦听器只获得进度
    10
  • 如果同时删除这两个选项,则会得到默认值
    0
此分析基于WorkManager 2.4.0版

因此,我发现下面的方法更好,并且总是可靠地显示您的连锁店工作的各个工人的进度

我有两个工人需要一个接一个地管理。如果第一项工作完成,则完成50%的工作,第二项工作完成时将完成100%

两名工人

class Worker1(context: Context, workerParameters: WorkerParameters) : Worker(context,workerParameters) {

override fun doWork(): Result {
    for (i in 1..5) {
        Log.e("worker", "worker1----$i")
    }
    return Result.success(Data.Builder().putInt("progress",50).build())
  }
}

class Worker2(context: Context, workerParameters: WorkerParameters) : Worker(context,workerParameters) {

override fun doWork(): Result {
    for (i in 5..10) {
       Log.e("worker", "worker1----$i")
    }
    return Result.success(Data.Builder().putInt("progress",100).build())
  }
}
活动内部

    workManager = WorkManager.getInstance(this)

    workRequest1 = OneTimeWorkRequest.Builder(Worker1::class.java)
            .addTag(TAG_SAVING_PROGRESS)
            .build()

    workRequest2 = OneTimeWorkRequest.Builder(Worker2::class.java)
            .addTag(TAG_SAVING_PROGRESS)
            .build()


   findViewById<Button>(R.id.btn).setOnClickListener(View.OnClickListener { view ->

        workManager?.
        beginUniqueWork(TAG_SAVING_PROGRESS,ExistingWorkPolicy.REPLACE,workRequest1)
                ?.then(workRequest2)
                ?.enqueue()
    })

    progressBar = findViewById(R.id.progressBar)

     workManager?.getWorkInfoByIdLiveData(workRequest1.id)
            ?.observe(this, Observer { workInfo: WorkInfo? ->
                if (workInfo != null && workInfo.state == WorkInfo.State.SUCCEEDED) {
                    val progress = workInfo.outputData
                    val value = progress.getInt("progress", 0)
                    progressBar?.progress =  value
                }
            })

    workManager?.getWorkInfoByIdLiveData(workRequest2.id)
            ?.observe(this, Observer { workInfo: WorkInfo? ->
                if (workInfo != null && workInfo.state == WorkInfo.State.SUCCEEDED) {
                    val progress = workInfo.outputData
                    val value = progress.getInt("progress", 0)
                    progressBar?.progress =  value
                }
            })
workManager=workManager.getInstance(此)
workRequest1=OneTimeWorkRequest.Builder(Worker1::class.java)
.addTag(标记保存进度)
.build()
workRequest2=OneTimeWorkRequest.Builder(Worker2::class.java)
.addTag(标记保存进度)
.build()
findViewById(R.id.btn).setOnClickListener(View.OnClickListener{View->
工作经理?。
开始工作(标记保存进度,现有工作策略。替换,工作请求1)
?然后(工作请求2)
?.排队()
})
progressBar=findViewById(R.id.progressBar)
workManager?.getWorkInfoByIdLiveData(workRequest1.id)
?观察(观察者{workInfo:workInfo?->
if(workInfo!=null&&workInfo.state==workInfo.state.successed){
val progress=workInfo.outputData
val value=progress.getInt(“progress”,0)
progressBar?进度=值
}
})
workManager?.getWorkInfoByIdLiveData(workRequest2.id)