展示运行WorkManager工作器的详细进度

8
我希望使用新的JetPack WorkManager(链接到codelabs)组件替换现有数据同步系统中的作业调度方面(位于应用程序的沙箱分支中)。我的现有系统运行良好,但是WorkManager中的一些新功能将会很有用(例如链接)。
我的当前系统使用共享的LiveData将正在进行中的作业的进度通信到任何UI元素(在我的情况下为RecyclerView)上观察它(实际上我正在ViewModel中进行SwitchMapping,转换成SyncItem列表)。
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等)可用于检索带有一个或多个WorkStatus的LiveData,但这些只报告一种粗略状态(正在运行、成功、失败、取消)。
推荐的通信进度的方式是什么(例如“已下载546/1234项”)?setOutputData/getOutputData配对似乎更多用于Worker之间的通信(当我需要链接时),而不是与UI交互。
附上屏幕截图,显示了用户打开同步状态页面时的情况(2项已完成,其余正在进行中)。

screenshot of syncing in progress

在最终产品中,用户将能够取消任何正在进行的作业并重新发出一次性工作请求。通常情况下,这些作业将由PeriodicWorkRequest触发。
2个回答

12

本地支持

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

报告工作者的进度:

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类型表示,它是一个可序列化的属性容器(类似于输入和输出,并受相同限制的约束)。

查看Android文档


8

最好的方法是将中间进度写入您自己的数据存储并公开一个LiveData<>。我们正在考虑在未来的alpha版本中添加此功能。


1
谢谢Rahul,从某种意义上说,这就是我目前使用的方法,只不过我使用单例对象作为数据存储。我可能需要持久化进度数据(我假设WM可以在应用关闭时启动)。将其作为官方功能会很好。 - Andre Artus
这其实很简单。我只是添加了一个表格,包括键、名称、进度、总数和查询来设置总数(并清除进度)以及更新进度。稍后可以详细说明。 - Andre Artus
这样的功能将受到热烈欢迎,WorkManager是Google到目前为止为Android开发者提供的最佳API。增加更多功能将会非常棒。 - Jonathan Dunn
我也对此非常感兴趣,我的使用情况与您类似:我想将下载进度发送给观察者。 - scholt
1
这个解决方案已不再合适。现在可以本地查看进度报告。请参见下面的答案。 - Paulo Pereira

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接