Android RxLife is a lightweight RxJava life cycle management library (2)

Time:2019-10-9

In Android RxLife, a lightweight RxJava Lifecycle Management Library (1), we explainedlift,composeThe use of these two operators, and how RxJava causes memory leaks, and how RxLife solves RxJava memory leaks. No more explanations here. If you haven’t seen it yet, please read back.

This article mainly explains the use and function of as operator in RxLife in the latest version 1.0.4.

Gradle dependence

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

Welcome star for source code download

Students who have read the last article know that they are using it.lift,composeWhen these two operators are used, we stipulate that there are no other operators in the downstream except subscribe operator. Then this regulation is not code level regulation. It needs extra attention from developers when developing. Obviously, this scheme is not perfect. So can we stipulate it from code level? At this time we will invite our protagonist to play!

As operator

Let’s take a look first.asHow to use the operator. (The following code runs in Activity by default)

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

That’s all right? Yes, it’s that simple. thatas How to avoid the downstream will not appear exceptsubscribeWhat about other operators? Let’s first look at the useasOperator, what is returned?

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

The return is aObservableLifeObject, what the hell is this? Go in and have a look

/**
 * 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,ObservableLifeThere are only a series of classes.subscribeMethod, and followObservableInsidesubscribeThe method is one-to-one correspondence, and the function is the same. Now, we’ll see. It turned out.asThe operator returns a custom object, and the object provides only a series ofsubscribeMethod, so as to avoid the downstream will not appear other operators, and avoid the risk of memory leaks.

Here,asThe principle of operator is clear. Let’s take a look at it again.asOther uses of operators.

Designated Life Cycle Closure Pipeline

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

Specifies the observer to call back in the main thread

Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
        As (RxLife. asOnMain (this)//asOnMain stands for callback in 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 thread callbacks and lifecycles at the same time

Observable.intervalRange(1, 100, 0, 200, TimeUnit.MILLISECONDS)
        // Callback in the main thread and specify to close the pipeline at onStop, or other lifecycles, without specifying the default on Destroy to close the pipeline
        .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,asOperator usage is so much, if there is a better idea, please let me know.

Little Eggs

The as series methods in the RxLife class are applicable to Observable, Flowable, Parallel Flowable, Single, Maybe, Completable, all of which have the same principle. Here we will not explain them one by one.

If you have any questions, please leave a message. I will answer it in the first time.

extend

RxLife sends requests in conjunction with HttpSender, which is hardly too cool.

For details of HttpSender, click on HttpSender OkHttp + RxJava Ultra-Useful and Super-Powerful Http Request Framework

Recommended Today

Mongoose error: getaddrinfo ENOTFOUND localhost localhost:27017

{ Error: getaddrinfo ENOTFOUND localhost localhost:27017 at errnoException (dns.js:50:10) at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26) code: ‘ENOTFOUND’, errno: ‘ENOTFOUND’, syscall: ‘getaddrinfo’, hostname: ‘localhost’, host: ‘localhost’, port: 27017 } mongoose.connect(‘mongodb://localhost:27017/db1’,{ poolSize:5, useNewUrlParser: true },err=>{ if(err){ console.error(err) }else { Console.log (‘mongodb successfully connected ‘) } }) Try changing localhost to 127.0.0.1 mongoose.connect(‘mongodb://127.0.0.1:27017/db1’,{ poolSize:5, useNewUrlParser: true },err=>{ if(err){ console.error(err) […]