I am investigating the use of RxJava/Retrofit within my current Android Application.
My Android application has to support many RestFul Web Service calls to maintain both User and reference data.
Although I call many different API's, at a high level they can be grouped into a small set of Call "patterns".
For example all my API calls employ the same Completable InitialProcess, RetryProcess and ErrorProcess.
What I would like to do is create a Base Class, (Step) Builder, and/or Factory solution that allows me to provide just the unique RxJava stages and have them combined with the "Common" stages mentioned above.
The solution will allow me to specify subscribeOn()/observeOn() as well as allowing me the choice of blockingWait() or subscribe() etc.
For example say that I need the following operation sequence:-
commonInitialProcess()
.andThen(Completable.defer(() -> uniqueCompletableProcessX()))
.andThen(Single.defer(() -> uniqueSingleProcessA())))
.doOnSuccess(commonSuccessProcess())
.ignoreElement()
.andThen(Single.defer(() -> uniqueSingleProcessB())))
.doOnSuccess(commonSuccessProcess())
.ignoreElement()
.andThen(uniqueCompletableProcessY())
.retryWhen(commonRetryWhenProcess())
.doOnComplete(uniqueCompleteProcess())
.doOnError(commonErrorProcess())
.blockingAwait();
I would supply
uniqueCompletableProcessX()
uniqueSingleProcessA()
uniqueSingleProcessB()
uniqueCompletableProcessY()
uniqueCompleteProcess()
And receive back the complete sequence shown above, which I can then execute with blockingAwait().
In another example
commonInitialProcess()
.andThen(Completable.defer(() -> uniqueCompletableProcessZ()))
.andThen(Single.defer(() -> uniqueSingleProcessC())))
.doOnSuccess(commonSuccessProcess())
.retryWhen(commonRetryWhenProcess())
.doOnComplete(uniqueCompleteProcessZ())
.doOnError(commonErrorProcess())
.subscribe();
I would supply
uniqueCompletableProcessZ()
uniqueSingleProcessC()
uniqueCompleteProcessZ()
And receive back the complete sequence shown above, which I can then execute with subscribe().
I've tried developing a Step Builder to support the High Level types
This is mode Step builder
public class FigurateSequence extends Sequence {
private static final int COMMON_INITIAL_PROCESS = 0;
private static final int UNIQUE_COMPLETABLE_STEP_A = 1;
private static final int UNIQUE_SINGLE_STEP_B = 0;
public FigurateSequence(final FigurateSequenceBuilder figurateSequenceBuilder) {
COMPLETABLES.addAll(figurateSequenceBuilder.getCompletables());
SINGLES.addAll(figurateSequenceBuilder.getSingles());
}
public static Step_0001 builder() {
return new FigurateSequenceBuilder();
}
public interface Step_0001 {
Step_0002 first(final Completable completable);
}
public interface Step_0002 {
Build second(final Single<String> single);
}
public interface Build {
FigurateSequence build();
}
public static class FigurateSequenceBuilder implements Step_0001, Step_0002, Build {
private final List<Completable> completables = new LinkedList<>();
private final List<Single<String>> singles = new LinkedList<>();
/**
*
*/
private FigurateSequenceBuilder() {
}
@Override
public Step_0002 first(final Completable completable) {
completables.add(completable);
return this;
}
@Override
public Build second(final Single<String> single) {
singles.add(single);
return this;
}
@Override
public FigurateSequence build() {
return new FigurateSequence(this);
}
/**
* @return the completables
*/
public List<Completable> getCompletables() {
return completables;
}
/**
* @return the singles
*/
public List<Single<String>> getSingles() {
return singles;
}
}
public void execute() {
COMPLETABLES.get(COMMON_INITIAL_PROCESS)
.andThen(Completable.defer(() -> COMPLETABLES.get(UNIQUE_COMPLETABLE_STEP_A)))
.andThen(Single.defer(() -> SINGLES.get(UNIQUE_SINGLE_STEP_B)))
.subscribe();
}
}
and Base Sequence Class
public class Sequence {
protected final List<Completable> COMPLETABLES = new LinkedList<>();
protected final List<Single<String>> SINGLES = new LinkedList<>();
public Sequence() {
COMPLETABLES.clear();
SINGLES.clear();
COMPLETABLES.add(getCommonInitialProcess());
}
/**
* @return
*
*/
private Completable getCommonInitialProcess() {
return Completable.create(new CompletableOnSubscribe() {
@Override
public void subscribe(final CompletableEmitter emitter) throws Exception {
Thread.sleep(500);
System.out.println("CommonInitialProcess()");
emitter.onComplete();
}
});
}
}
Which works, however its use is still "clunky"
FigurateSequence.builder().first(getUniqueCompletableProcess_A()).second(getUniqueSingleProcess_A()).build().execute();
However there are some cases that are still troublesome
Such as when I have both a default and custom "Step Sequences".
for example if I have a default DoOnError() and a custom DoOnError() how do I define my step builders inner interfaces to cope with an "optional" step?