Description
Currently, Maybe.compose()
requires a Function<? super Maybe<T>, ? extends MaybeSource<R>>
and Single.compose()
requires something similar
While other types have FlowableTransformer
and CompletableTransformer
. Would it make sense to bring them into the same pattern? Aside from consistency, early testing for me shows that the generics gymnastics involved in Maybe
and Single
's Function
approaches is a major headache, as any parameterized stream type gets lost and requires manual specification, forfeiting the ability to reuse APIs.
Consider RxLifecycle, which historically has just returned an implementation of the required Transformer.
someSingle
.compose(RxLifecycle.bind(this).forSingle())
.subscribe();
This works for simple unparameterized types, but breaks down when parameterized types come in.
// Same result with both Single and Maybe. Screenshot is Maybe, example below is Single.
// The type is now a List<T> of some type T
someListSingle
.compose(Confine.to(this).forSingle()) // Compiler error because R type instance not found
.subscribe();
Where Confine.to
returns a bridging helper like this:
public static class LifecycleTransformer2<T> implements FlowableTransformer<T, T> {
// Delegate transformer, what's currently returned by RxLifecycle.bind()
private LifecycleTransformer<T> delegate;
public static <T> LifecycleTransformer2<T> create(@NonNull LifecycleTransformer<T> delegate) {
return new LifecycleTransformer2<>(delegate);
}
private LifecycleTransformer2(@NonNull LifecycleTransformer<T> delegate) {
this.delegate = delegate;
}
public Function<Maybe<T>, MaybeSource<T>> forMaybe() {
return source -> {
Observable<T> o = toV1Observable(source.toFlowable());
o = delegate.call(o);
return RxJavaInterop.toV2Flowable(o).singleElement();
};
}
public Function<? super io.reactivex.Single<T>, ? extends SingleSource<T>> forSingle() {
return new Function<io.reactivex.Single<T>, SingleSource<T>>() {
@Override
public SingleSource<T> apply(io.reactivex.Single<T> source) throws Exception {
Single<T> o = toV1Single(source);
o = (Single<T>) delegate.forSingle().call((Single<Object>) o);
return RxJavaInterop.toV2Single(o);
}
};
}
public CompletableTransformer forCompletable() {
return source -> {
Completable o = toV1Completable(source);
o = delegate.forCompletable().call(o);
return RxJavaInterop.toV2Completable(o);
};
}
@Override
public Publisher<? extends T> apply(Flowable<T> source) throws Exception {
Observable<T> o = toV1Observable(source);
o = delegate.call(o);
return RxJavaInterop.toV2Flowable(o);
}
}
FlowableTransformer
and CompletableTransformer
work fine, but the other two have been really tricky to nail down.