Android-RxJava2背压、生命周期

Android-RxJava2背压、生命周期

背压

产生原因
当上下游在不同的线程中,通过Observable发射,处理,响应数据流时,如果上游发射数据的速度快于下游接收处理数据的速度,这样对于那些没来得及处理的数据就会造成积压,这些数据既不会丢失,也不会被垃圾回收机制回收,而是存放在一个异步缓存池中,如果缓存池中的数据一直得不到处理,越积越多,最后就会造成内存溢出,这便是响应式编程中的背压(backpressure)问题

Flowable:支持背压

 /**
         *  被观察者(背压)的创建
         * BackpressureStrategy.BUFFER  背压策略
         */
        Flowable.create(new FlowableOnSubscribe<Object>() {
            @Override
            public void subscribe(FlowableEmitter<Object> emitter) throws Exception {
                emitter.onNext("Flowable-luo");
                emitter.onComplete();
//                emitter.onError();
            }
        }, BackpressureStrategy.BUFFER)	//添加背压策略
                .subscribe(new Subscriber<Object>() {

                    @Override
                    public void onSubscribe(Subscription s) {
                        s.request(Long.MAX_VALUE);
                    }

                    @Override
                    public void onNext(Object o) {

                    }

                    @Override
                    public void onError(Throwable t) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

BackpressureStrategy背压策略

  • MISSING(MissingEmitter):在此策略下,通过Create方法创建的Flowable相当于没有指定背压策略,不会对通过onNext发射的数据做缓存或丢弃处理,需要下游通过背压操作符。
  • ERROR(ErrorAsyncEmitter):在此策略下,如果放入Flowable的异步缓存池中的数据超限了,则会抛出MissingBackpressureException异常。
  • BUFFER(BufferAsyncEmitter):部维护了一个缓存池SpscLinkedArrayQueue,其大小不限,此策略下,如果Flowable默认的异步缓存池满了,会通过此缓存池暂存数据,它与Observable的异步缓存池一样,可以无限制向里添加数据,不会抛出MissingBackpressureException异常,但会导致OOM。
  • DROP(DropAsyncEmitter):在此策略下,如果Flowable的异步缓存池满了,会丢掉上游发送的数据
  • LATEST(LatestAsyncEmitter):与Drop策略一样,如果缓存池满了,会丢掉将要放入缓存池中的数据,不同的是,不管缓存池的状态如何,LATEST都会将最后一条数据强行放入缓存池中,来保证观察者在接收到完成通知之前,能够接收到Flowable最新发射的一条数据

来看看里面的代码FlowableCreate

  @Override
    public void subscribeActual(Subscriber<? super T> t) {
        BaseEmitter<T> emitter;
		//判断背压模式 进行创建
        switch (backpressure) {
        case MISSING: {
            emitter = new MissingEmitter<T>(t);
            break;
        }
        case ERROR: {
            emitter = new ErrorAsyncEmitter<T>(t);
            break;
        }
        case DROP: {
            emitter = new DropAsyncEmitter<T>(t);
            break;
        }
        case LATEST: {
            emitter = new LatestAsyncEmitter<T>(t);
            break;
        }
        default: {
            emitter = new BufferAsyncEmitter<T>(t, bufferSize());
            break;
        }
        }

        t.onSubscribe(emitter);
        try {
            source.subscribe(emitter);
        } catch (Throwable ex) {
            Exceptions.throwIfFatal(ex);
            emitter.onError(ex);
        }
    }

背压策略的解决思路 响应式拉取:响应式拉取是观察者主动去被观察者那里拉取事件,而被观察者则是被动等待通知在发射事件。

Subscription 响应式拉取方式,来设置下游对数据的请求数量,上游可以根据下游的需求量,按需发送数据,如果不显示调用request()则默认下游的需求量为零,所以运行下面的代码后,上游Flowable发射的数据不会交给下游Subscriber处理。

在这里插入图片描述

//
package org.reactivestreams;

public interface Subscription {
  ......
}

这是一个接口,居然是接口,那肯定是有实现

    static final class ObserveOnSubscriber<T> extends BaseObserveOnSubscriber<T>
    implements FlowableSubscriber<T> {
     SimpleQueue<T> queue;	//队列
 @Override
        public void onSubscribe(Subscription s) {
            if (SubscriptionHelper.validate(this.s, s)) {
                this.s = s;

                if (s instanceof QueueSubscription) {
                    @SuppressWarnings("unchecked")
                    QueueSubscription<T> f = (QueueSubscription<T>) s;

                    int m = f.requestFusion(ANY | BOUNDARY);

                    if (m == SYNC) {
                        sourceMode = SYNC;
                        queue = f;
                        done = true;
						//回调出去,将自己返回出去了
                        actual.onSubscribe(this);
                        return;
                    } else
                    if (m == ASYNC) {
                        sourceMode = ASYNC;
                        queue = f;

                        actual.onSubscribe(this);

                        s.request(prefetch);

                        return;
                    }
                }

                queue = new SpscArrayQueue<T>(prefetch);

                actual.onSubscribe(this);

                s.request(prefetch);
            }
        }		

		//同步
		@Override
        void runSync() {
		......
		}
		//异步
	   @Override
        void runAsync() {
			......
		}
	  @Override
        void runBackfused() {
			.......
		}
		
	.......
	//关键的代码贴出来
 		@Nullable
        @Override
        public T poll() throws Exception {
        //queue队列取值
            T v = queue.poll();
            if (v != null && sourceMode != SYNC) {
                long p = produced + 1;
                if (p == limit) {
                    produced = 0;
                    s.request(p);
                } else {
                    produced = p;
                }
            }
            return v;
        }
	
	}

生命周期

生命周期RxLifecycle

我们先来看看这段代码,用了里面的计时器
这里我们没有加入生命周期管理,当我们从该界面跳转到另一个界面的时候,这个计时器不会自动取消订阅,也就是说还会有一直在打印,如果用内存查看工具,我们会发现存在开启定时器的这个Activity会存在内存泄露的问题

  Observable.interval(1, TimeUnit.SECONDS)
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.i("MainActivity","onCreate() 中取消订阅");
                    }
                })
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long num) throws Exception {
                        Log.i("MainActivity","onCreate() 开始"+num);
                    }
                });

接下来我们来添加生命周期管理-RxLifecycle
先添加依赖

 //rxlifecycle
    implementation 'com.trello.rxlifecycle3:rxlifecycle:3.0.0'
    implementation 'com.trello.rxlifecycle3:rxlifecycle-android:3.0.0'
    implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.0.0'

再看看使用

1、我们继承了RxAppCompatActivity;
2、添加了.compose(this.bindUntilEvent(ActivityEvent.PAUSE))
compose这个操作符就是可以让我们添加自定义的操作符,也就是可以在这个操作符中添加自己的代码块。

package com.lk.rxjavatest;

import android.os.Bundle;
import android.util.Log;

import com.trello.rxlifecycle3.android.ActivityEvent;
import com.trello.rxlifecycle3.components.support.RxAppCompatActivity;

import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

public class MainActivity extends RxAppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Observable.interval(1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .doOnDispose(new Action() {
                    @Override
                    public void run() throws Exception {
                        Log.i("MainActivity","onCreate() 中取消订阅");
                    }
                })
                //生命周期管理
                .compose(this.<Long>bindUntilEvent(ActivityEvent.PAUSE))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long num) throws Exception {
                        Log.i("MainActivity","onCreate() 开始"+num);
                    }
                });
        
    }

}

我们来看看这个compose操作符;
需要传进来的参数是ObservableTransformer泛型接口,

    @SuppressWarnings("unchecked")
    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> compose(ObservableTransformer<? super T, ? extends R> composer) {
        return wrap(((ObservableTransformer<T, R>) ObjectHelper.requireNonNull(composer, "composer is null")).apply(this));
    }

我们再来看看bindUntilEvent这个方法;
它里面的返回值是LifecycleTransformer;
我们跟进去LifecycleTransformer这个类看看
LifecycleTransformer实现了5个被观察者的接口…

 @Override
    @NonNull
    @CheckResult
    public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
        return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
    }


public final class LifecycleTransformer<T> implements ObservableTransformer<T, T>,
                                                      FlowableTransformer<T, T>,
                                                      SingleTransformer<T, T>,
                                                      MaybeTransformer<T, T>,
                                                      CompletableTransformer
{
	//这是啥? 这是被观察者
	final Observable<?> observable;
	......
}

记得我们这个自定义操作符吗?
.compose(this.bindUntilEvent(ActivityEvent.PAUSE))
这个bindUntilEvent 我们来看看RxAppCompatActivity 这个父类
里面bindUntilEvent这个方法
里面各种生命周期的回调

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.trello.rxlifecycle3.components.support;

import android.os.Bundle;

import com.trello.rxlifecycle3.LifecycleProvider;
import com.trello.rxlifecycle3.LifecycleTransformer;
import com.trello.rxlifecycle3.RxLifecycle;
import com.trello.rxlifecycle3.android.ActivityEvent;
import com.trello.rxlifecycle3.android.RxLifecycleAndroid;

import androidx.annotation.CallSuper;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import io.reactivex.Observable;
import io.reactivex.subjects.BehaviorSubject;

public abstract class RxAppCompatActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {

    private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();

    @Override
    @NonNull
    @CheckResult
    public final Observable<ActivityEvent> lifecycle() {
        return lifecycleSubject.hide();
    }

    @Override
    @NonNull
    @CheckResult
    public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
    //看到这里是不是很眼熟,我们在看看这个传入的ActivityEvent
        return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
    }

    @Override
    @NonNull
    @CheckResult
    public final <T> LifecycleTransformer<T> bindToLifecycle() {
        return RxLifecycleAndroid.bindActivity(lifecycleSubject);
    }

    @Override
    @CallSuper
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        lifecycleSubject.onNext(ActivityEvent.CREATE);
    }

    @Override
    @CallSuper
    protected void onStart() {
        super.onStart();
        lifecycleSubject.onNext(ActivityEvent.START);
    }

    @Override
    @CallSuper
    protected void onResume() {
        super.onResume();
        lifecycleSubject.onNext(ActivityEvent.RESUME);
    }

    @Override
    @CallSuper
    protected void onPause() {
        lifecycleSubject.onNext(ActivityEvent.PAUSE);
        super.onPause();
    }

    @Override
    @CallSuper
    protected void onStop() {
        lifecycleSubject.onNext(ActivityEvent.STOP);
        super.onStop();
    }

    @Override
    @CallSuper
    protected void onDestroy() {
        lifecycleSubject.onNext(ActivityEvent.DESTROY);
        super.onDestroy();
    }
}

ActivityEvent 我们来看看这个类
这是一个枚举类,定义了各个生命周期的枚举
我们上面代码中指定了ActivityEvent.PAUSE
也就是会在这个生命周期的时候,会帮我们自动取消订阅

package com.trello.rxlifecycle3.android;

/**
 * Lifecycle events that can be emitted by Activities.
 */
public enum ActivityEvent {

    CREATE,
    START,
    RESUME,
    PAUSE,
    STOP,
    DESTROY

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值