Skip to content

2.x: Should Maybe and Single have a corresponding Transformers? #4650

Closed
@ZacSweers

Description

@ZacSweers

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.

screenshot 2016-10-01 02 21 10

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions