Android RxLife A Lightweight RxJava Lifecycle Management Library

Keywords: Android Gradle github OkHttp

stay Android RxLife A Lightweight RxJava Lifecycle Management Library (1) In this article, we explain the use of lift,compose, and how RxJava causes memory leaks and how RxLife Solves RxJava memory leaks.No more explanations here, if you haven't seen it, please read back

This article mainly explains the use of as operator in RxLife 1.0.4 and its role.

gradle dependency

implementation 'com.rxjava.rxlife:rxlife:1.0.4'

Source Download Welcome to star

Students who have read the previous article know that when using the lift and compose operators, we have stipulated that no other operator can appear downstream except the subscribe operator. Then this is not a code-level rule, which requires extra attention from developers when developing. Obviously this scheme is not perfect, can we stipulate it from the code-level?Now it's time to ask our protagonist to play!

as operator

Let's first see how the as operator works.(The following code runs in Activity by default)

Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
        .as(RxLife.as(this)) //this is a Lifecycle Owner object
        .subscribe(aLong -> {
            Log.e("LJX", "accept=" + aLong);
        });

Is that OK?Yes, it's that simple.So how does as avoid operators other than subscribe appearing downstream?Let's first look at what is returned using the as operator?

ObservableLife<Long> observableLife = Observable
        .intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
        .as(RxLife.asOnMain(this));

What's the ghost of returning an ObservableLife object?Go in and see

/**
 * User: ljx
 * Date: 2019/4/18
 * Time: 18:40
 */
public class ObservableLife<T> extends RxSource<Observer<? super T>> {

    private Observable<T> upStream;

    ObservableLife(Observable<T> upStream, LifecycleOwner owner, Event event, boolean onMain) {
        super(owner, event, onMain);
        this.upStream = upStream;
    }

    @Override
    public final Disposable subscribe() {
        return subscribe(Functions.emptyConsumer(), Functions.ON_ERROR_MISSING, Functions.EMPTY_ACTION, Functions.emptyConsumer());
    }

    public final Disposable subscribe(Consumer<? super T> onNext) {
        return subscribe(onNext, Functions.ON_ERROR_MISSING, Functions.EMPTY_ACTION, Functions.emptyConsumer());
    }

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {
        return subscribe(onNext, onError, Functions.EMPTY_ACTION, Functions.emptyConsumer());
    }

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
                                      Action onComplete) {
        return subscribe(onNext, onError, onComplete, Functions.emptyConsumer());
    }

    public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError,
                                      Action onComplete, Consumer<? super Disposable> onSubscribe) {
        ObjectHelper.requireNonNull(onNext, "onNext is null");
        ObjectHelper.requireNonNull(onError, "onError is null");
        ObjectHelper.requireNonNull(onComplete, "onComplete is null");
        ObjectHelper.requireNonNull(onSubscribe, "onSubscribe is null");

        LambdaObserver<T> ls = new LambdaObserver<T>(onNext, onError, onComplete, onSubscribe);

        subscribe(ls);

        return ls;
    }


    @Override
    public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
            observer = RxJavaPlugins.onSubscribe(upStream, observer);

            ObjectHelper.requireNonNull(observer, "The RxJavaPlugins.onSubscribe hook returned a null Observer. Please change the handler provided to RxJavaPlugins.setOnObservableSubscribe for invalid null returns. Further reading: https://github.com/ReactiveX/RxJava/wiki/Plugins");

            subscribeActual(observer);
        } catch (NullPointerException e) { // NOPMD
            throw e;
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            // can't call onError because no way to know if a Disposable has been set or not
            // can't call onSubscribe because the call might have set a Subscription already
            RxJavaPlugins.onError(e);

            NullPointerException npe = new NullPointerException("Actually not, but can't throw other exceptions due to RS");
            npe.initCause(e);
            throw npe;
        }
    }

    private void subscribeActual(Observer<? super T> observer) {
        Observable<T> upStream = this.upStream;
        if (onMain) {
            upStream = upStream.observeOn(AndroidSchedulers.mainThread());
        }
        upStream.onTerminateDetach().subscribe(new LifeObserver<>(observer, owner, event));
    }
}

Carefully, you will find that there is only a series of subscribe methods in the ObservableLifeclass, which correspond to one-to-one subscribe methods in ObservableLifeclass and have the same functions.By doing so, we understand that the original as operator returned a custom object that provided only a series of subscribe methods, thus avoiding the dangers of memory leaks and other operators downstream.

Now that we have explained the principles of the as operator, let's look at the other uses of the as operator.

Specify life cycle shutdown pipeline

Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
        //Specify closing pipelines at onStop or other life cycles without specifying closing pipelines at onDestroy by default
        .as(RxLife.as(this, Event.ON_STOP)) 
        .subscribe(aLong -> {
            Log.e("LJX", "accept=" + aLong + " Thread=" + Thread.currentThread());
        });

Specify observer callback on main thread

Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
        .as(RxLife.asOnMain(this)) //asOnMain represents a callback on the main thread
        .subscribe(aLong -> {
            Log.e("LJX", "accept=" + aLong + " Thread=" + Thread.currentThread());
        });
        
        //Equivalent to
Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
        .observeOn(AndroidSchedulers.mainThread())
        .as(RxLife.as(this))
        .subscribe(aLong -> {
            Log.e("LJX", "accept=" + aLong + " Thread=" + Thread.currentThread());
        });

Specify both thread callback and lifecycle

Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
        //Callback on the main thread and specify to close the pipeline at onStop or other life cycles without specifying to close the pipeline at onDestroy by default
        .as(RxLife.asOnMain(this, Event.ON_STOP)) 
        .subscribe(aLong -> {
            Log.e("LJX", "accept=" + aLong + " Thread=" + Thread.currentThread());
        });
        //Equivalent to
Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
        .observeOn(AndroidSchedulers.mainThread())
        .as(RxLife.as(this, Event.ON_STOP))
        .subscribe(aLong -> {
            Log.e("LJX", "accept=" + aLong + " Thread=" + Thread.currentThread());
        });

ok, as operator usage is so much, if there is a better idea, please tell me.

Small egg

The as-series methods in the RxLife class all apply to Observable, Flowable, ParallelFlowable, Single, Maybe, Completable, which are six observer objects. The reason is the same, but they are not explained here.

If you have any questions, please leave a message and I will answer them in the first place.

extend

RxLife Combination HttpSender Sending requests is hardly cool.

For more information on HttpSender, Click HttpSender OkHttp+RxJava Ultra Useful, Super Powerful Http Request Framework

Posted by buck2bcr on Sun, 05 May 2019 13:56:38 -0700