Giter Site home page Giter Site logo

RxLifecycle interop module about autodispose HOT 8 CLOSED

uber avatar uber commented on April 29, 2024
RxLifecycle interop module

from autodispose.

Comments (8)

ZacSweers avatar ZacSweers commented on April 29, 2024 1

Cool. Let's make the default to map to AutoDispose's exception, since I think that will be the common case. That way it'll be picked up by the autodispose plugin hook for lifecycle exceptions too

from autodispose.

bangarharshit avatar bangarharshit commented on April 29, 2024

What will be the use case for such a module?

from autodispose.

ZacSweers avatar ZacSweers commented on April 29, 2024

So when I say which in turn should also lend support for its various components (RxActivity, etc) above, I'm referring to things like RxActivity or implement LifecycleProvider such that anyone currently using RxLifecycle could use AutoDispose rather seemlessly without needing to go redo all their plumbing up front

from autodispose.

bangarharshit avatar bangarharshit commented on April 29, 2024

One solution can be to have static util methods to provide the different type of scopers for Lifecycleprovider.

For MaybeScoper just listen to Lifecycleprovider and emit when it emits (just rough sample code).

  public static <T> Function<Observable<?>, ObservableSubscribeProxy<Object>> lifeCycleProvider(final LifecycleProvider<T> lifecycleProvider) {
    Maybe<T> maybe = Maybe.create(new MaybeOnSubscribe<T>() {
      @Override public void subscribe(final MaybeEmitter<T> e) throws Exception {
        lifecycleProvider.lifecycle().subscribe(new Consumer<T>() {
          @Override public void accept(T t) throws Exception {
            e.onSuccess(t);
          }
        }, new Consumer<Throwable>() {
          @Override public void accept(Throwable throwable) throws Exception {
            // It shouldn't be thrown ideally. Throwing so that AutoDisposingObserverImpl dispose in the error callback.
            e.onError(throwable);
          }
        });
      }
    });
    return AutoDispose.with(maybe).forObservable();
  }

For Lifecyclescopeprovider the consumer can provide the CorrespondingEvents (or the defaults from RXLifecycle can be used).

  public static <T>LifecycleScopeProvider<T> lifecycleScopeProvider(LifecycleProvider<T> lifecycleProvider, final Function<T, T> correspondingEvents) {
    final BehaviorSubject<T> behaviorSubject = BehaviorSubject.create();
    lifecycleProvider.lifecycle().subscribe(new Consumer<T>() {
      @Override public void accept(T t) throws Exception {

      }
    });
    return new LifecycleScopeProvider<T>() {
      @Override public Observable<T> lifecycle() {
        return behaviorSubject.hide();
      }

      @Override public Function<T, T> correspondingEvents() {
        return correspondingEvents;
      }

      @Nullable @Override public T peekLifecycle() {
        return behaviorSubject.getValue();
      }
    };
  }

  public static <T>LifecycleScopeProvider<T> activityLifecycleScopeProvider(LifecycleProvider<T> lifecycleProvider) {
    return lifecycleScopeProvider(lifecycleProvider, RxLifecycleAndroid.ACTIVITY_LIFECYCLE);
  }

Not sure if this is the best approach as it still needs some plumbing. Also, since Rx lifecycle has multiple modules so it may require multiple interop modules.

For RxActivity, I am not sure what will be equivalent of bindUntilEvent

from autodispose.

ZacSweers avatar ZacSweers commented on April 29, 2024

The API should just return scope providers for autodispose to use, not act as an alternative to autodispose itself. Also FYI - The API has changed, Scopers are deprecated.

So my thoughts on this are basically:

  • Have an RxLifecycleInterop class with static factories
  • A bindLifecycle method: static ScopeProvider bindLifecycle(LifecycleProvider<E> provider) that calls the bindToLifecycle method under the hood and creates a ScopeProvider based on its returned transformer
  • A bindUntilEvent method: static ScopeProvider bindLifecycle(LifecycleProvider<E> provider, E event) that does the above but to bindUntilEvent().

An implementation could look like this:

static ScopeProvider bindLifecycle(LifecycleProvider<E> provider) {
  return new ScopeProvider() {
    @Override
    Maybe<?> requestScope() {
      return provider.lifecycle()
          .compose(provider.bindToLifecycle())  // Interop layer. This stream will now complete upon lifecycle end
          .ignoreElements() // Listen for just completions
          .toMaybe()  // Back to Maybe<?>
          .defaultIfEmpty(SOME_STATIC_THROWAWAY_OBJECT) // Because RxLifecycle just completes when it's done, we want to coerce that to a faked "onSuccess" here
    }
  }
}

There will be caveats, but that's ok. This will not really be a LifecycleScopeProvider, but rather just a ScopeProvider that defers to RxLifecycle's boundary checks under the hood.

One question could be if we want to coerce RxLifecycle's OutsideLifecycleException to an AutoDispose LifecycleEndedException via onErrorResumeNext. Pros is it keeps the translation consistent (RxLifecycle in, AutoDispose out). Cons is any of the user's existing error handling logic looking for those will not catch this. We'll probably just have to make a call on what to do by default, but we could add an overload that accepts a boolean param to allow the user to specify which one they want to do. Or we could just decide to transform all of them and offer a utility transformer to convert errors back to RxLifecycle errors if they want (.compose(autoDisposeLifecycleErrorsToRxLifecycleErrors()))

from autodispose.

bangarharshit avatar bangarharshit commented on April 29, 2024

Got it. Static utility method for error is much better than either forcing them or breaking their existing chain.

I think the best part of the approach is that we doesn't need separate methods for RX Activity as the caller takes care of provider.bindToLifeCycle()

from autodispose.

bangarharshit avatar bangarharshit commented on April 29, 2024

Looking at RxLifecycle source code RXLifeCycle.java and OutsideLifeCycleException.java, it treats LifecycleEndedException as normal terminal event. Unlike AutoDispose, it doesn't throw the error to the user and silently completes the stream.

from autodispose.

ZacSweers avatar ZacSweers commented on April 29, 2024

Oh right, in that case we don't need to add the error switch at all then

from autodispose.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.