【问题标题】:Showing detailed progress for running WorkManager workers显示运行 WorkManager 工作人员的详细进度
【发布时间】:2018-11-05 14:55:45
【问题描述】:

我想用新的 JetPack WorkManager(链接到 codelabs)组件(在应用程序的沙箱分支中)替换我现有数据同步系统的作业调度方面。我现有的系统运行良好,但 WorkManager 中的一些新功能会派上用场(例如链接)。

我当前的系统使用共享的LiveData 将正在进行的作业的进度传达给观察它的任何 UI 元素(在我的情况下为 RecyclerView)(我实际上是在 ViewModel 中将 SwitchMapping 到列表中SyncItems)

data class SyncItem(
        val title: String,
        private var _progress: Int,
        var total: Int) : BaseObservable() {

    var progress: Int
        @Bindable get() = _progress
        set(value) {
            _progress = value
            notifyPropertyChanged(BR.progress)
        }
}

新的WorkManager 组件有几种方法(getStatusByIdgetStatusesByTag 等)可用于检索具有一个或多个 WorkStatuses 的 LiveData,但这些仅报告课程粒度状态(运行、成功、失败、取消)。

向 UI 传达进度(例如“已下载 546/1234 个项目”)的推荐方式是什么? setOutputData/getOutputData 对似乎更多地用于Workers(链接时我需要)之间的通信,而不是与 UI 通信。

附件是用户打开同步状态页面(已完成 2 项,正在进行中)时的屏幕截图(在我的应用的 [测试] 版本中使用我的旧方法)。

在最终产品中,用户将能够取消任何正在进行的工作并重新发出一次性工作请求。通常这些工作会被PeriodicWorkRequest解雇。

【问题讨论】:

    标签: android android-jetpack android-workmanager


    【解决方案1】:

    本机支持

    implementation 'androidx.work:work-runtime:2.5.0'
    

    报告 Worker 的进度:

    public class FooWorker extends Worker {
    
        public FooWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
            super(context, workerParams);
        }
    
        @NonNull
        @Override
        public Result doWork() {
            try {
                setProgressAsync(new Data.Builder().putInt("progress", 0).build());
                Thread.sleep(1000);
                setProgressAsync(new Data.Builder().putInt("progress", 50).build());
                Thread.sleep(1000);
                setProgressAsync(new Data.Builder().putInt("progress", 100).build());
    
                return Result.success();
            } catch (InterruptedException e) {
                e.printStackTrace();
                return Result.failure();
            }
        }
    }
    

    观察 Worker 的进度:

    WorkManager.getInstance(context).getWorkInfosForUniqueWorkLiveData("test").observe(lifecycleOwner, new Observer<List<WorkInfo>>() {
            @Override
            public void onChanged(List<WorkInfo> workInfos) {
                if (workInfos.size() > 0) {
                    WorkInfo info = workInfos.get(0);
                    int progress = info.getProgress().getInt("progress", -1);
                    //Do something with progress variable
                }
    
            }
        });
    

    ListenableWorker 现在支持 setProgressAsync() API,它允许它保持中间进度。这些 API 允许开发人员设置 UI 可以观察到的中间进度。进度由 Data 类型表示,它是一个可序列化的属性容器(类似于输入和输出,并受到相同的限制)。

    See Android Documentation

    【讨论】:

      【解决方案2】:

      最好的方法是将中间进度写入您自己的数据存储并公开LiveData&lt;&gt;。我们正在考虑在未来的 Alpha 版中添加此功能。

      【讨论】:

      • 感谢 Rahul,从某种意义上说,这就是我正在使用当前方法所做的事情,除了我使用单例对象作为数据存储。我可能需要保留进度数据(我假设 WM 可以在应用程序关闭时启动)。将其作为官方功能会很好。
      • 这其实很简单。我刚刚添加了一个带有键、名称、进度、总计和查询的表,以设置总计(和清除进度)并更新进度。以后可以展开。
      • 非常感谢这样的功能,WorkManager 是 Google 迄今为止为 Android 开发的最好的 API。它的更多功能会很棒。
      • 我也会对此非常感兴趣,类似的用例:我想将下载进度发送给观察者
      • 这个解决方案不再有意义。进度报告现在本地可用。请参阅下面的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多