如何可视化RxJava图的执行?

时间:2017-06-08 13:20:49

标签: java rx-java rx-java2

假设我有一些复杂的SingleMaybeObservable个对象链,它们执行某些任务。

例如:

// 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...
}

推荐的方法是什么?

1 个答案:

答案 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主线程。