How can I visualize the execution of RxJava graphs?

Suppose I have several complex chains of objects Single

, Maybe

and Observable

that do some tasks.

For example:

// 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)));
}

      

These chains can run across multiple threads.

The problem is that I would like to make these tasks flow for the user without interfering with their logic where possible.

For example, the above task might show:

+-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

      

Ideally, I would also like to show the hierarchy of tasks. This is currently only encoded in the Java call graph.

My modern thinking:

  • Change each one Single

    to Observable

    where the last item is the result and the others are progress updates.
  • Enter event classes for each step in the task.

I think this will make the code less readable and lead to a lot of boiler stove.

public final class DownloadProgress {
    public final float progress;
    // etc..
}

// etc... 

public final class FetchReleaseProgress {
    public final Variant<DownloadProgress, HashingProgress, UnpackProgress, ParseProgress> progress;
    // etc...
}

      

What is the recommended approach?

+3


source to share


1 answer


you are on the right track, you can write a complete ui model that represents the ui events you are interested in. I will give your case here as an example

+-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

      

and the model could be something like this:

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
}

      

then with Rxjava you can use the previous model like this:



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))
...

      

then when you sign up you can use this ui model to update you like

downloadObservable.subscribe(model -> 
if(model.getProgress()!= 100){
Timber.d(model.getDownloading())
Timber.d(model.getHashing())
Timber.d(model.getUnpacking))
//...
}

      

the nice part of this way is that your ui logic is decoupled from your request logic and you can safely go to the main android theme.

0


source







All Articles