假设我有一些复杂的Single
,Maybe
和Observable
个对象链,它们执行某些任务。
例如:
// Download, unzip and parse a release
public static Single<Release> fetchRelease(final Release release) {
final Path cachePath = getCachePath(release);
return download(release.url, cachePath, true).ignoreElements()
.andThen(hash(cachePath))
.flatMap(fileHash -> unzip(cachePath)
.andThen(parseFile(unzipTargetPath)));
}
这些链可能跨多个线程运行。
问题在于我想向用户呈现这些任务的进度,而不会在可能的情况下弄乱他们的逻辑。
例如,上述任务可能会显示:
+-Fetching release 1.0... Done
+-Downloading https://www.example.com/v1.0.0.zip 100%
+-Hashing Library/Caches/Example/v1.0.0.zip... Done
+-Unpacking Library/Caches/Example/v1.0.0.zip
+-src.. Done
+-tests... Done
+-resources... Done
+-Parsing release... Done
理想情况下,我还希望显示任务的层次结构。目前这只在Java调用图中编码。
我目前的想法是:
Single
更改为Observable
,其中最后一个元素是结果,其他元素是进度更新。 我认为这会降低代码的可读性并导致大量的锅炉。
public final class DownloadProgress {
public final float progress;
// etc..
}
// etc...
public final class FetchReleaseProgress {
public final Variant<DownloadProgress, HashingProgress, UnpackProgress, ParseProgress> progress;
// etc...
}
推荐的方法是什么?
答案 0 :(得分:0)
你是以正确的方式,你可以写一个完整的ui模型,代表你感兴趣的ui事件,我会以你的案例为例
+-Fetching release 1.0... Done
+-Downloading https://www.example.com/v1.0.0.zip 100%
+-Hashing Library/Caches/Example/v1.0.0.zip... Done
+-Unpacking Library/Caches/Example/v1.0.0.zip
+-src.. Done
+-tests... Done
+-resources... Done
+-Parsing release... Done
并且模型可能是这样的:
final class DownloadUiModel {
private float progress;
private String hashing;
private String downloading;
private String unpacking;
private String done;
private DownloadUiModel(float progress, String hashing //..etc) {
}
//getters
//setters
}
然后使用Rxjava,您可以使用以前的模型:
download(release.url, cachePath, true)
.ignoreElements()
.map(response -> downloadUiModel.setDownloading(release.url))
.andThen(hash(cachePath))
.map(response -> downloadUiModel.setHashing(cachePath))
.flatMap(fileHash -> unzip(cachePath)
.andThen(parseFile(unzipTargetPath)))
.map(response -> downloadUiModel.setUnzipping(unzipTargetPath))
...
然后在订阅时,你可以使用这个ui模型来更新你,就像这样
downloadObservable.subscribe(model ->
if(model.getProgress()!= 100){
Timber.d(model.getDownloading())
Timber.d(model.getHashing())
Timber.d(model.getUnpacking))
//...
}
关于这种方式很好的部分,你的ui逻辑与你的请求逻辑分离,你可以很容易地安全地切换到Android主线程。